Have you ever found yourself wishing you could manage everything as if it were a Kubernetes cluster? Good news: Thanks to Crossplane, an open source project developed by the Cloud Native Computing Foundation (CNCF), you can do this – or at least something approximating it. Crossplane makes it possible to manage external resources, such as servers and applications that are not part of your Kubernetes cluster, in the same way you can manage pods and nodes.

Crossplane doesn’t actually let you turn your entire existence into a Kubernetes cluster, but it does make it possible to manage pretty much any type of IT resource (or at least any resource that has an API) using the Kubernetes tooling and configuration strategies you already know and love.

Intrigued? Keep reading to learn the ins and outs of how Crossplane works in Kubernetes, why it’s useful, how to set up Kubernetes Crossplane, and best practices for getting the most out of the technology.

What is Crossplane in Kubernetes?

Crossplane is a cloud-native framework for managing infrastructure, applications, and services that are external to Kubernetes using native Kubernetes tooling. Put another way, Crossplane lets you use a Kubernetes cluster as a universal control plane that can manage not just pods, nodes, and other resources that live inside your cluster, but also external servers, applications, and so on.

To use Crossplane, you use the same process as you would when managing internal Kubernetes resources. First, you define a resource declaratively with YAML. You then apply the configuration with kubectl, and voilà: Kubernetes automatically creates and manages the resource for you.

Behind the scenes, Crossplane does its magic by using the APIs of external resources to manage them. Pretty much anything that you can manage via an API can be managed through Crossplane.

Crossplane vs. Terraform

If you’re thinking that Crossplane sounds a lot like Terraform or other Infrastructure-as-Code (IaC) platforms, you’re not wrong. Crossplane and Terraform are similar in that Terraform also lets you define resources declaratively, then apply configurations automatically.

The key difference, though, is that Terraform, like most IaC solutions, is a standalone framework that comes with its own tooling, configuration languages, and syntax. In contrast, Crossplane uses the languages and tooling that are built into Kubernetes. If you know how to use Kubernetes, you’ll likely find it very easy to use Crossplane as well.

Crossplane is also different from Terraform and most other IaC frameworks in that, like Kubernetes itself, Crossplane uses a declarative approach to configuration management. This means you describe the desired state of a resource via Crossplane, and Kubernetes then applies the configuration automatically. Terraform uses an imperative approach that requires admins to define more explicitly how the system should create and manage resources.

Key features of Crossplane

To dive deeper into what Crossplane does and why it’s so cool, here’s a look at its major features and capabilities:

  • Kubernetes-native infrastructure management: As we mentioned, Crossplane makes it possible to treat external resources as if they were native Kubernetes resources. You can manage them using the same tooling, concepts, and workflows that you’d use for any standard Kubernetes pod, node, service, or other resource.
  • Extensibility through CRDs: Crossplane uses Kubernetes custom resource definitions (CRDs) to tell the cluster how to manage external resources via their APIs. This means that if Crossplane doesn’t already support a resource you want to manage, you can implement support by creating a CRD to extend Crossplane.
  • Multi-cloud and hybrid cloud support: Crossplane doesn’t limit you to managing resources in just one environment at a time. It works seamlessly with resources hosted across multiple clouds or in a hybrid cloud architecture – which means you could, for example, set up a control plane that manages some resources in AWS and others in Azure.
  • Continuous reconciliation: Because Crossplane uses a declarative configuration approach, it automatically and continuously “reconciles” resources by comparing their current state to the desired state, then attempting to update them if these states are not in sync.
  • Policy enforcement and governance: You can define management and governance policies in Crossplane, and then let Kubernetes enforce them automatically. This is another way in which Crossplane offers advantages that aren’t always present in traditional IaC tools.
  • Developer-centric API design: As we mentioned, Crossplane relies on APIs to do its magic. This means that if you like working with APIs – as developers tend to do – you’ll probably like working with Crossplane.

Benefits of Crossplane

You certainly don’t need to use Crossplane to manage external resources. You can use IaC platforms like Terraform or whatever native management tooling the resources support. But by opting for Crossplane instead, you open the door to several key Kubernetes benefits.

Unified control plane

Crossplane consolidates management of all resources – those that actually live inside your Kubernetes cluster and those external to it – via a single, unified control plane. This means you get one set of tools to work with. A unified control plane also provides a central source of truth for all of your on-prem and cloud infrastructure, applications, and services.

Declarative infrastructure management

As we noted, Crossplane is distinguished from conventional IaC tools by its declarative management approach. It lets you describe what you want to happen, and Crossplane and Kubernetes then make it happen (assuming doing so is possible).

Declarative management can simplify provisioning because it requires fewer details or instructions about how resources should operate. It can also improve reliability because the system can automatically fix or heal resources whose actual state deviates from the desired state.

Extensibility

We said it above, but we’ll say it again: Because Crossplane uses CRDs to define interactions with external resources, it’s highly extensible. You’re not limited to working only with resources hosted in specific clouds or other platforms. As long as the resources you want to manage have an API, you can manage them via Crossplane.

This benefit is especially important if you want to create a framework for platform engineering, a practice that focuses on making it easy for an organization’s developers to spin up the resources they require to work. Crossplane addresses this need by letting you spin up resources of any type.

How to implement Crossplane in Kubernetes environments

The process for setting up Crossplane is relatively straightforward, but it requires several distinct steps.

1. Install Crossplane

Crossplane runs as a set of pods within your cluster. The easiest way to install Crossplane is using the Crossplane Helm chart. You can do this with the following commands:

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

2. Configure provider credentials

The third-party environments that Crossplane interfaces with are known as providers. For example, a provider could be Amazon Web Services. You need to configure access credentials so that Crossplane can log into the provider environment using your account and manage resources on your behalf.

The exact process for configuring provider credentials varies between cloud providers. But in general, it involves first creating a text file that stores your access credentials. For example, the following file would work for AWS:

[default]
aws_access_key_id =[AWS access key ID]
aws_secret_access_key =[AWS secret access key]

To make the credentials accessible to Crossplane, create a Kubernetes secret that references the file:

kubectl create secret generic my-creds -n crossplane-system --from-file=creds=./credentials.txt

3. Define ProviderConfig resources

ProviderConfig is a type of resource that connects Crossplane to an external account. It references the secret you created in the previous step to tell Crossplane which credentials to use to connect to the provider.

For example, the following ProviderConfig resource uses the my-creds secret created in step 2:

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

4. Create managed resources

At this point, the Crossplane setup is able to begin creating and managing external resources.

The types of resources you can work with depend on what your provider supports (although again, pretty much everything that is accessible via a provider API can be managed as a Crossplane resource). As an example, imagine you want to create an S3 bucket on AWS. You’d define the resource using YAML, as follows (note here that we’re defining the resource kind as a Bucket in the provider metadata):

apiVersion: s3.aws.upbound.io/v1beta1
kind: Bucket
metadata:
  name: sample-S3-bucket
spec:
  forProvider:
	region: us-east-1
  providerConfigRef:
	name: default

Save your YAML to a file (like bucket-config.yaml) and apply it to your cluster with kubectl:

kubectl apply -f bucket-config.yaml

Kubernetes will now automatically create an S3 bucket in your AWS account based on the configuration you specified.

5. Create and manage composite resources

In addition to creating and managing standard resources, Crossplane supports composite resources. Composite resources are custom resources that you can use to group and manage sets of infrastructure components as single units. They work by letting you define a custom API for managing multiple resources.

For instance, here’s a composite resource definition for a composite PostgreSQL instance:

apiVersion: example.org/v1alpha1
kind: CompositePostgreSQLInstance
metadata:
  name: my-db
spec:
  parameters:
	storageGB: 20
	region: us-west-2
  compositionRef:
	name: example-db-composition

As with a standard resource, you’d save this definition as a file and apply it with kubectl.

Deploying Crossplane resources via GitOps of CI/CD

You can take Crossplane-based automation up another level by using GitOps or CI/CD automations to create and manage resources for you.

The key idea behind this approach is to define resources in YAML files, store the files in Git, and then apply the resource configurations automatically.

For instance, imagine you want to deploy an S3 storage bucket on AWS using GitOps. You’d first set up the provider credentials and a ProviderConfig resource as above. Then, you’d define your S3 bucket using code like the following:

apiVersion: s3.aws.upbound.io/v1beta1
kind: Bucket
metadata:
  name: sample-S3-bucket
spec:
  forProvider:
	region: us-east-1
  providerConfigRef:
	name: default

But instead of applying the file directly, you’d save it in a Git repository. You’d also configure a tool like Flux, which automatically watches your Git repos and applies changes to your cluster – so when you create the resource definition for the S3 bucket, Flux will apply it for you, as long as you’ve configured Flux to watch the appropriate Git repository.

This approach is useful if you want to use Crossplane to manage many resources, and/or if you change your configurations frequently, because it lets you create and modify resources directly from Git rather than having to do it inside your cluster.

Real-world use cases for Crossplane

Now that we’ve talked all about what Crossplane can do and how it does it, let’s discuss some real-world scenarios where Crossplane would come in handy.

Multi-cloud resource provisioning

Creating and managing resources across distinct clouds (like AWS and Azure) can be challenging because each cloud has different tooling – so if you provision the resources using each cloud’s native tooling, you end up having to work with multiple tool sets. With Crossplane, however, you can simply configure a provider for each cloud that you want to work in, then use Crossplane to create resources seamlessly in each cloud environment.

You could achieve something similar, of course, using IaC tools like Terraform. But as we mentioned, the advantage of Crossplane is that it lets you do everything directly from Kubernetes. If you already have a Kubernetes cluster running in one cloud environment, you can use Crossplane to turn it into a control plane for your entire multi-cloud architecture.

Infrastructure automation in CI/CD pipelines

Crossplane is a powerful solution when you want to automate cloud infrastructure setup as part of a CI/CD pipeline.

In this case, you can use a GitOps tool like Flux to apply resource configurations instantly and automatically. This eliminates the need to provision resources manually, which saves time. It also lets you trigger automated infrastructure changes in response to events in your CD pipeline – such as spinning up a new resource to test an application release candidate and spinning it back down when testing is done.

In addition to saving time, this approach helps ensure that you don’t accidentally leave resources running, and it helps you avoid paying for resources when you’re not using them. It also comes in handy if you want to use Crossplane as a cloud-native framework for platform engineering because anyone within your organization who needs to launch a resource can do so directly from GitHub.

Simplifying tooling and account management

To use Crossplane, you need an account for each provider whose resources you want to manage. But Crossplane eliminates the need to log in manually to each account because you can do everything through a single control plane. It also lets you create and manage resources using a consolidated set of tools – namely, YAML code and kubectl – rather than having to juggle the various tools offered by each provider.

For these reasons, Crossplane is a great solution for teams that need to work with diverse platforms and tools, but want to simplify the overall management experience.

Best practices for Crossplane deployment

| Practice | Description | |---|---| | Efficient API and schema design | Design custom APIs with efficiency in mind. | | Monitoring resource usage | Monitor resource usage and consider setting quotas. | | Documentation | Document Crossplane-based resources and workflows. | | Secrets management | Avoiding insecure secrets management when defining credentials for Crossplane cloud providers. | | Version control | Use version control to track changes to Crossplane-managed resources. |

To get the most value from Crossplane, consider the following best practices:

  • Efficient API and schema design: The ability to work with custom resources via custom APIs is key to what makes Crossplane so powerful. That said, a poorly designed API can become the weakest link in a Crossplane-based workflow. When designing APIs and schemas, aim for efficiency and simplicity.
  • Monitoring of resource usage and quotas: Like any type of Kubernetes resource, Crossplane Kubernetes resources that consume too many CPU, memory, or storage resources can cost money and undercut the performance of other workloads. Assigning resource quotas can mitigate this risk.
  • Documentation and team collaboration: The ability to manage resources using a central control plane is only useful if everyone on your team knows how the approach works and which procedures to follow. For that reason, it’s best practice to document your Crossplane resources and policies and make the documentation accessible to your team.
  • Secrets management and security: As with any tool that requires the use of sensitive data, such as usernames and passwords, it’s critical to manage Crossplane secrets safely – and to understand the capabilities and limitations of secrets in Kubernetes.
  • Version control: Version-controlling your Crossplane resource definitions using a system like Git gives you the ability to revert problematic changes quickly, as well as track how your resources have evolved over time.

Limitations of Crossplane in Kubernetes

While Crossplane is a great tool, it is subject to some limitations, such as:

  • Learning curve: Learning the basics of Crossplane is easy enough if your goal is to deploy standard resources. But the Crossplane learning curve becomes steeper if you want to do things like define custom APIs or work with composite resources.
  • Varying provider capabilities: Since Crossplane’s ability to manage resources is based on the APIs that cloud providers (or other infrastructure providers) offer, it’s more powerful with some platforms and environments than others.
  • Difficulty importing existing infrastructure: It’s possible to “import” resources that you didn’t create via Crossplane into Crossplane so that you can manage them through Kubernetes. But the process for doing this is relatively complex, and Crossplane works best when you create all of your resources using Crossplane from the start. 
  • Dependency on Kubernetes: Crossplane’s ability to turn Kubernetes into a universal control plane is part of what makes it so amazing. However, this can be a downside in cases where something goes wrong with your cluster – such as a control plane node failure that makes the cluster inoperable or exhaustion of resources for the Crossplane Kubernetes pods. If that happens, Crossplane becomes a single source of failure because any resources you’re trying to manage with it may not work as intended. You could always manage the resources directly from the external platforms, but it can be difficult to pivot quickly to that approach if your Kubernetes cluster suddenly goes down.
  • Added monitoring and observability complexity: Managing resources through Crossplane complicates Kubernetes monitoring and observability. When something goes wrong with an external resource, you may not know immediately whether the problem lies with the way Crossplane is trying to manage the resource, or if it’s an issue linked to the external provider. For example, if a Crossplane-managed resource is unreachable, it could be because of a bug in Crossplane. But it could also be due to an issue like a networking outage on the external platform where the resource lives. Since Crossplane can only “see” resources from the vantage point of Kubernetes, it doesn’t provide visibility into external performance problems.

How groundcover enhances Crossplane in Kubernetes

As a comprehensive Kubernetes observability solution, groundcover provides the visibility you need to detect problems like failing Crossplane pods or control plane node issues quickly. We can also help you determine which resource quotas to assign to Crossplane-based resources to balance performance with cost. And, since groundcover can monitor external platforms as well as those managed through Kubernetes, we make it easy to know whether performance issues are linked to Kubernetes itself or an external platform.

When you entrust your external resource management to Crossplane via a unified control plane, you can trust groundcover to deliver visibility into Crossplane itself, and to help keep all of your resources running smoothly.

Crossing over to Crossplane

To be sure, Crossplane isn’t for everyone. If you don’t actually enjoy living and dying by kubectl, you may prefer another approach to resource management. But for folks who enjoy consolidated tooling and workflows – not to mention benefits like declarative configuration management – a Crossplane universal control plane is likely to feel like an incredible solution.

Sign up for Updates

Keep up with all things cloud-native observability.

We care about data. Check out our privacy policy.