Crossplane, Replacing Terraform?


In the previous blog post I have dipped into basics of crossplane and ways to work with it. Since then the project have come up with many new features. Let’s dig into some of the new ways we can use crossplane to make Infra management a little better. The core advantage of Crossplane is that not only it helps you create infrastructure with ease, it also prevents from configuration drift by continuous reconciliation. Another advantage is that you can manage custom API groups using RBAC policies similar to native Kubernetes APIs.
Core Components
Rather than devs raising a jira to create cloud resources, what if they can create themselves with a simple yaml file? Just as you write a definition file for pod what if you can write a definition file for a database?. Let see how it can be done but before that I have to introduce you to some concepts and definitions. This table briefly summarizes the definitons. Please go through the below table.
Component | Abbv | Scope | Summary | Example |
Provider | cluster | Creates new Kubernetes Custom Resource Definitions for an external service. | provider-aws-ec2, provider-aws-eks, provider-gcp-gke | |
ProviderConfig | PC | cluster | Applies settings for a Provider. | |
Managed Resource | MR | cluster | A Provider resource created and managed by Crossplane inside the Kubernetes cluster. | Bucket, dynamoDB, AMI, VPC |
Composition | cluster | A template for creating multiple managed resources at once. | ||
Composite Resources | XR | cluster | Uses a Composition template to create multiple managed resources as a single Kubernetes object. | |
CompositeResourceDefinitions | XRD | cluster | Defines the API schema for Composite Resources and Claims | XIRSA, xSQLInstances |
claims | XC | namespace | Like a Composite Resource, but namespace scoped. |
Crossplane Functions
There are multiple functions that are supported by Crossplane. Functions are essential to write concise steps and remove redundancy. They also allow us to use conditionals and loops when creating resources(Imagine creating multiple subnets for a VPC). Composition can be written as steps of functions, each step is used to create different Managed Resources. There are many programming languages which you can use to write functions like Python and Golang. Along with those, there configuration languages such as KCL and CUE which can be a great help to write compositions.
An Example
Enough with the theory but let’s see how we can leverage these in creating infrastructure. Let us take a scenario where I want to let users create VPC with subnets. Here is how my composition will look like
And here is my CompositeResourceDefinition(XRD) to serve this composition. It lays out an OpenAPI format to call the XRD like required parameters and their format.
These two files lays out the template for resource creation. Now I can create multiple Composite Resources or Composite Claims(namespace scoped) using the above two components. If I wanted to create a claim file in default namespace, here is how it will look like
Here is my claim file, things to be noted here are compositionRef
is not necessary. I can use something like compositionSelector
and get appropriate composition with matching labels. So only I apply these definitions, I can see all the resources reflected in AWS. I can also track the resource creation from CLI using commands like crossplane beta trace
(CLI must be installed)
➜ network crossplane beta trace dbnetworks.db.srujanpakanati.com storage-network
NAME SYNCED READY STATUS
DBNetwork/storage-network (default) True False Waiting: Claim is waiting for composite resource to become Ready
└─ XDBNetwork/storage-network-c5sqw True False Creating: ...s-east-2b-192-168-64-0-18-private, and storage-network-c5sqw-vpc
├─ Subnet/storage-network-c5sqw-2zscc True False Creating
├─ Subnet/storage-network-c5sqw-lcf4k True True Available
└─ VPC/storage-network-c5sqw-qk9wj True True Available
➜ network crossplane beta trace dbnetworks.db.srujanpakanati.com storage-network
NAME SYNCED READY STATUS
DBNetwork/storage-network (default) True False Waiting: Claim is waiting for composite resource to become Ready
└─ XDBNetwork/storage-network-c5sqw True False Creating: ...s-east-2b-192-168-64-0-18-private, and storage-network-c5sqw-vpc
├─ Subnet/storage-network-c5sqw-2zscc True True Available
├─ Subnet/storage-network-c5sqw-lcf4k True True Available
└─ VPC/storage-network-c5sqw-qk9wj True True Available
➜ network k describe vpc storage-network-c5sqw-qk9wj
Name: storage-network-c5sqw-qk9wj
Namespace:
Labels: crossplane.io/claim-name=storage-network
crossplane.io/claim-namespace=default
crossplane.io/composite=storage-network-c5sqw
Annotations: crossplane.io/composition-resource-name: storage-network-c5sqw-vpc
crossplane.io/external-create-pending: 2024-12-07T21:01:18Z
crossplane.io/external-create-succeeded: 2024-12-07T21:01:18Z
crossplane.io/external-name: vpc-094642de4b2a114f6
API Version: ec2.aws.upbound.io/v1beta1
Kind: VPC
Metadata:
Creation Timestamp: 2024-12-07T21:01:16Z
Finalizers:
finalizer.managedresource.crossplane.io
Generate Name: storage-network-c5sqw-
Generation: 3
Owner References:
API Version: db.srujanpakanati.com/v1alpha1
Block Owner Deletion: true
Controller: true
Kind: XDBNetwork
Name: storage-network-c5sqw
UID: 753881fe-b9fe-4953-8007-1a14114b520f
Resource Version: 42765
UID: e8fee79f-4d34-4078-af3f-f14cff6f1518
Spec:
Deletion Policy: Delete
For Provider:
Cidr Block: 192.168.0.0/16
Enable Dns Hostnames: true
Enable Dns Support: true
Instance Tenancy: default
Region: us-east-2
Tags:
Name: storage-network-c5sqw
Crossplane - Kind: vpc.ec2.aws.upbound.io
Crossplane - Name: storage-network-c5sqw-qk9wj
Crossplane - Providerconfig: default
Init Provider:
Management Policies:
*
Provider Config Ref:
Name: default
Status:
At Provider:
Arn: arn:aws:ec2:us-east-2:135227014767:vpc/vpc-094642de4b2a114f6
assignGeneratedIpv6CidrBlock: false
Cidr Block: 192.168.0.0/16
Default Network Acl Id: acl-051e434241f655bd1
Default Route Table Id: rtb-0ea107329a3ddc22b
Default Security Group Id: sg-0c3510da7998ad5ae
Dhcp Options Id: dopt-016e84c858d19736f
Enable Dns Hostnames: true
Enable Dns Support: true
Enable Network Address Usage Metrics: false
Id: vpc-094642de4b2a114f6
Instance Tenancy: default
ipv6AssociationId:
ipv6CidrBlock:
ipv6CidrBlockNetworkBorderGroup:
ipv6IpamPoolId:
ipv6NetmaskLength: 0
Main Route Table Id: rtb-0ea107329a3ddc22b
Owner Id: 135227014767
Tags:
Name: storage-network-c5sqw
Crossplane - Kind: vpc.ec2.aws.upbound.io
Crossplane - Name: storage-network-c5sqw-qk9wj
Crossplane - Providerconfig: default
Tags All:
Name: storage-network-c5sqw
Crossplane - Kind: vpc.ec2.aws.upbound.io
Crossplane - Name: storage-network-c5sqw-qk9wj
Crossplane - Providerconfig: default
Conditions:
Last Transition Time: 2024-12-07T21:01:33Z
Reason: Available
Status: True
Type: Ready
Last Transition Time: 2024-12-07T21:01:18Z
Reason: ReconcileSuccess
Status: True
Type: Synced
Last Transition Time: 2024-12-07T21:01:30Z
Reason: Success
Status: True
Type: LastAsyncOperation
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal CreatedExternalResource 5m50s managed/ec2.aws.upbound.io/v1beta1, kind=vpc Successfully requested creation of external resource
➜ network k get dbnetworks.db.srujanpakanati.com
NAME SYNCED READY CONNECTION-SECRET AGE
storage-network True True 14m
As you can see that finally my network components have come up. To put everything in a nutshell
XRD → lays down the schema of the API
Composition → A blueprint to create composite resources for that API (Like a Class)
Claim → Like an object which gets a physical copy of that Composition
Please note that I have written the composition to create SQLInstances hence the API extension dbnetworks.db.srujanpakanati.com. It is just a naming convention but nothing else
Conclusion
This is a very basic use-case of Crossplane. There are lot many features like importing existing resources, managementPolicies, writeConnectionSecretToRef and using ExternalSecretStore etc. Crossplane will be a good transition from Terraform if you are already on Kubernetes.
Subscribe to my newsletter
Read articles from Srujan Reddy directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Srujan Reddy
Srujan Reddy
I am a Kubernetes Engineer passionate about leveraging Cloud Native ecosystem to run secure, efficient and effective workloads.