Multi-Cloud State: Synchronizing Workloads with Crossplane
Bottom Line
Crossplane eliminates provider-specific IaC silos by using Kubernetes as a universal control plane to manage stateful resources like RDS and Cloud SQL through a single, unified API.
Key Takeaways
- ›Decouple infrastructure from provider-specific APIs using Composite Resource Definitions (XRDs).
- ›Achieve 100% workload portability by standardizing on Kubernetes-native primitives for stateful services.
- ›Reduce configuration drift by 85% through continuous Crossplane reconciliation loops.
- ›Centralize secret management and infrastructure metadata within a single K8s control plane.
Managing stateful workloads across multiple cloud providers has historically been the 'final boss' of cloud engineering. While Kubernetes solved compute portability, stateful resources like managed databases (RDS, Cloud SQL) remained trapped behind provider-specific Terraform modules and proprietary APIs. In 2026, Crossplane has emerged as the definitive solution, transforming your Kubernetes cluster into a universal control plane that treats infrastructure as a first-class citizen alongside your application code.
The Multi-Cloud State Dilemma
Most organizations fail at multi-cloud because they attempt to build an abstraction layer that targets the lowest common denominator. This leads to 'Cloud Sprawl,' where engineers must maintain duplicate logic for AWS, GCP, and Azure. Crossplane flips this script by allowing you to define your own 'Internal Developer Platform' (IDP) APIs.
Bottom Line
By April 2026, the standard for multi-cloud state is no longer 'portability by migration,' but 'portability by abstraction.' Crossplane XRDs allow you to provision an XPostgresInstance that automatically maps to AWS RDS or GCP Cloud SQL based on the environment context, reducing boilerplate by up to 70%.
Prerequisites & Environment Setup
Prerequisites
- A Kubernetes cluster (v1.29+) with Helm v3.12+ installed.
- Cloud credentials for AWS (IAM user with
AdministratorAccess) and GCP (Service Account withEditorrole). - kubectl-crossplane CLI plugin installed on your local machine.
- Access to a Data Masking Tool for scrubbing sensitive
kubeconfigor provider secrets before auditing.
Step 1: Installing Crossplane 1.18+
First, we need to bootstrap our Kubernetes cluster with the Crossplane control plane. As of April 22, 2026, we are utilizing the v1.18.2 release which includes optimized reconciliation logic for high-latency cross-region providers.
helm repo add crossplane-stable https://charts.crossplane.io/stable
helm repo update
helm install crossplane --namespace crossplane-system crossplane-stable/crossplane --create-namespace
Verify the installation by checking the pods in the crossplane-system namespace:
kubectl get pods -n crossplane-system
Step 2: Defining the Composite Resource Definition
The CompositeResourceDefinition (XRD) is your custom API. We will define a generic XPostgresInstance that defines the schema for what a database looks like at your company, regardless of which cloud it runs on.
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xpostgresinstances.database.example.org
spec:
group: database.example.org
names:
kind: XPostgresInstance
plural: xpostgresinstances
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
parameters:
type: object
properties:
storageGB:
type: integer
required:
- storageGB
Step 3: Implementing Cloud-Specific Compositions
This is where the magic happens. We create a Composition for AWS and one for GCP. When a developer requests a database, Crossplane selects the correct composition based on labels.
AWS RDS Composition Snippet
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: xpostgres.aws.rds
labels:
provider: aws
spec:
compositeTypeRef:
apiVersion: database.example.org/v1alpha1
kind: XPostgresInstance
resources:
- name: rdsinstance
base:
apiVersion: database.aws.upbound.io/v1beta1
kind: Instance
spec:
forProvider:
region: us-east-1
dbInstanceClass: db.t3.micro
engine: postgres
allocatedStorage: 20
--patch flag in Crossplane compositions to dynamically map your XRD storageGB value directly to the provider's native field (e.g., allocatedStorage in AWS vs diskSize in GCP).Step 4: Provisioning & Verification
To provision the resource, we create a CompositeResourceClaim (XRC). This is what an application developer would include in their application's Helm chart.
apiVersion: database.example.org/v1alpha1
kind: XPostgresInstance
metadata:
name: my-db-claim
namespace: production
spec:
parameters:
storageGB: 50
compositionSelector:
matchLabels:
provider: aws
Monitor the status of your synchronization using the following CLI commands:
- Check Claim Status:
kubectl get xpostgresinstance my-db-claim - Trace Infrastructure:
kubectl crossplane beta trace xpostgresinstance my-db-claim - Verify Cloud Resource: Log into the AWS Console and verify that the RDS instance is in
creatingoravailablestatus.
Troubleshooting Top-3 Sync Issues
Even with a robust control plane, multi-cloud synchronization can encounter hurdles. Here are the top three issues encountered in Crossplane 1.18:
- ProviderConfig Secret Mismatch: If your
ProviderConfigreferences a secret that doesn't exist or is in a different namespace, the controller will hang. Always verify withkubectl describe providerconfig. - Finalizer Deadlocks: If you delete a namespace before Crossplane can clean up the cloud resource, the
finalizerwill prevent deletion. Usekubectl patchto manually remove finalizers only as a last resort. - Permission Scoping: AWS IAM roles for Service Accounts (IRSA) must have the explicit
rds:CreateDBInstancepermission. Standard 'PowerUser' roles often lack specific tagging permissions required by Crossplane.
What's Next: Hybrid Cloud State
The next frontier in 2026 is Crossplane integration with Cilium ClusterMesh. This allows you not only to provision infrastructure across clouds but to create a transparent network layer where a service in EKS can reach a database in GKE without public ingress, using mTLS and SPIFFE identities managed by the same control plane.
Frequently Asked Questions
Is Crossplane a replacement for Terraform? +
How does Crossplane handle secret rotation for multi-cloud databases? +
Can I use Crossplane for on-premises infrastructure? +
Get Engineering Deep-Dives in Your Inbox
Weekly breakdowns of architecture, security, and developer tooling — no fluff.