Leveraging Crossplane to build single-tenant SaaS control planes on top of Kubernetes. | Sela.
Sela. | Cloud Better.

Leveraging Crossplane to build single-tenant SaaS control planes on top of Kubernetes.

Sela

As SaaS companies scale, one of the most critical architectural decisions they face is whether to adopt a single-tenant or multi-tenant model. While multi-tenancy offers cost efficiency and resource optimization, it also introduces challenges such as noisy neighbor effects, security risks, and limited customization. In contrast, a single-tenant model provides each customer with dedicated infrastructure, ensuring stronger isolation, security, and flexibility—features that enterprise customers often demand for compliance and customization reasons.

However, scaling a single-tenant SaaS platform presents significant infrastructure challenges. Now, imagine a SaaS platform deployed on Kubernetes, managing hundreds of isolated clusters—each requiring its own infrastructure, networking, and security configurations. Without automation, this quickly becomes a nightmare. Traditional Infrastructure-as-Code (IaC) tools like Terraform help with initial provisioning, but they lack continuous reconciliation, requiring manual interventions to maintain consistency across environments.

This blog post is dedicated to one such use-case and how we are leveraging the Kubernetes control plane in conjunction with Crossplane to solve these challenges.

Before we get started, we should introduce Crossplane. Crossplane is a control-plane extension for Kubernetes that enables the management of non-Kubernetes resources via Kubernetes’ declarative model and reconciliation loop. Effectively, this enables platform teams to provision and manage cloud resources using Kubernetes-native APIs, and enables us to achieve some typically challenging goals for SaaS companies who wish to offer a single-tenant deployment model to customers, including:

  • Automation of tenant provisioning across multiple AWS accounts.
  • Continuous reconciliation of infrastructure state to prevent drift.
  • The management of cloud resources at scale.
  • The ability to support multi-cloud and hybrid deployments without rewriting automation for each deployment type.

In this blog, we’ll show how we worked with the Flywheel team to transform the operation of its single-tenant SaaS infrastructure —eliminating manual effort and making scalability seamless.

 

Extending the Kubernetes Control Plane to Manage AWS Resources

In traditional Infrastructure-as-Code (IaC) workflows, provisioning cloud resources is often a one-time operation. Tools like Terraform are effective at defining infrastructure state, but they lack continuous reconciliation—requiring manual interventions to detect and correct drift. Crossplane extends Kubernetes’ declarative model beyond containerized workloads, enabling continuous lifecycle management of non-Kubernetes resources.

To achieve this, we deployed Crossplane in a dedicated management cluster—separating infrastructure control from application workloads. This cluster acts as the central orchestrator, continuously ensuring that cloud resources remain in their intended state.

Crossplane accomplishes this through Provider controllers, which serve as Kubernetes-native resource managers for external cloud services. These controllers watch for changes in desired infrastructure states—defined as Kubernetes Custom Resources (CRs)—and automatically reconcile discrepancies. Whether scaling databases, updating IAM roles, or provisioning networking components, Crossplane ensures that AWS resources remain in sync with Kubernetes-defined policies.

In collaboration with Flywheel, Sela designed this architecture to streamline the management of single-tenant SaaS deployments across multiple AWS accounts. Each tenant’s infrastructure is provisioned, monitored, and continuously reconciled through Kubernetes’ API, eliminating the need for external orchestration tools. This approach not only reduces operational overhead but also ensures consistent, policy-driven infrastructure management at scale.

 

Configuring Authorization for Multi-Cloud Lifecycle Management

To enable Crossplane to provision and manage infrastructure across multiple AWS accounts, we needed to establish a secure and scalable authorization mechanism between the management cluster and target AWS environments.

A key challenge in this setup was that our management cluster runs in Azure, while Crossplane needed permissions to manage AWS resources. To bridge this gap, we leveraged AWS Security Token Service (STS).

 

Bridging Azure Workload Identity with AWS STS

Since Kubernetes workloads in Azure authenticate using Entra ID (formerly Azure AD), we designed an authentication flow where:

  1. Azure pods use workload identity to assume continuously an Entra ID user.
  2. The Entra ID user is authorized to assume an AWS IAM role via STS.
  3. Crossplane’s AWS provider uses this assumed role to provision and reconcile AWS resources.

However, AWS’ provider lacked native support for this authentication method. To solve this, we deployed a sidecar container responsible for retrieving and refreshing the Azure web identity token when it expired. This token was then used to configure Crossplane’s AWS provider via the WebIdentity authentication method:

 

 

This setup ensured that Crossplane could continuously manage AWS resources from an Azure-hosted control plane without requiring static credentials.

 

Managing Multi-Tenant Deployments in Customer AWS Accounts

For Flywheel customers requiring deployments in their own AWS accounts, we configured cross-account permissions. This allowed us to use a role in Flywheel’s AWS account to manage a customer’s infrastructure, enabling the creation of Crossplane provider configurations specific to each customer account.

 

By leveraging multiple provider configurations, we were able to use the same AWS provider family to manage infrastructure across different AWS accounts, ensuring a scalable and flexible solution.

 

Designing Crossplane compositions

Once the Crossplane AWS provider is connected, we can define managed resources—cloud resources represented as Kubernetes objects within Crossplane. These include S3 buckets, EKS clusters, NodeGroups, and other AWS infrastructure components.

However, managing individual resources at scale becomes cumbersome and error prone. To address this, Crossplane Compositions allow us to bundle multiple managed resources into a single, reusable abstraction. This enables platform engineers to define infrastructure declaratively while embedding Flywheel-specific business logic.

 

Encapsulating Infrastructure with Crossplane Compositions

We designed three core Crossplane Compositions to standardize and simplify infrastructure provisioning:

  1. ClusterNetwork – Manages VPC-related resources, including VPCs, Subnets, RouteTables, Routes, and Gateways.
  2. KubeCluster – Handles EKS cluster provisioning, including NodeGroups, LaunchTemplates, and Add-ons.
  3. PodIdentity – Automates PodIdentityAssociation deployments, ensuring Kubernetes workloads inherit correct AWS IAM roles.

These Compositions allow Flywheel’s infrastructure to remain declarative, modular, and scalable, reducing operational overhead and improving consistency.

 

Enhancing Compositions with Go Templates and Dynamic Provider Selection

To support complex infrastructure patterns, we embedded Go template functions into our Compositions. This allowed us to:

  • Encode business logic directly within resource definitions.
  • Dynamically generate resource configurations based on input parameters.
  • Enable multi-account deployments by introducing a provider configuration variable within all Compositions.

By abstracting these details at the Composition level, we ensured that platform engineers could define infrastructure once and deploy it consistently across multiple AWS environments.

 

Defining a Kubernetes-Native Cluster Specification

To provision an EKS cluster, engineers only need to define ClusterNetwork and KubeCluster resources. The KubeClusterClaim CRD abstracts away the complexity of individual AWS components while providing flexibility in configuration:

This declarative approach ensures:

  • Scalability – Infrastructure definitions remain modular and reusable.
  • Simplicity – Engineers don’t need to manage low-level AWS details.
  • Portability – Future cloud providers can be integrated using the same Composition patterns.

With these Compositions, Crossplane doesn’t just provision infrastructure—it continuously manages its lifecycle, ensuring AWS resources remain in the desired state across their entire lifespan.

 

Automating Cluster Deployments with ArgoCD

With our Crossplane Composite Resources defined, deploying a new Kubernetes cluster is as simple as applying the necessary manifests to the management cluster. However, to ensure continuous, automated deployments, we integrate ArgoCD as a GitOps-based control mechanism.

ArgoCD continuously monitors a Git repository containing all infrastructure definitions and ensures that the management Kubernetes cluster remains in sync with the desired state. This enables a fully declarative infrastructure workflow:

  1. Engineers commit a cluster configuration to the Git repository.
  2. ArgoCD detects the change and applies the updated manifests.
  3. Crossplane provisions the required AWS resources, creating or updating an EKS cluster.

This process eliminates the need for manual cluster provisioning—platform operators simply update a Git repository to create, update, or destroy an EKS cluster.

 

Automating Application Deployments Post-Cluster Creation

Once an EKS cluster is provisioned, the next challenge is deploying workloads onto it. To automate this step, we use a Crossplane provider for ArgoCD, which extends GitOps automation beyond infrastructure provisioning.

This provider has three responsibilities:

  1. Extracts configuration variables from the cluster definition (e.g., cluster name, endpoint, authentication details) once Crossplane provisions it.
  2. Registers the new cluster in ArgoCD using the configuration variables.
  3. Ensures application manifests are deployed to the new cluster

By integrating Crossplane and ArgoCD, we fully automate both cluster provisioning and workload deployment, making it easy to manage a large fleet of single-tenant Kubernetes clusters.

 

GitOps-Driven SaaS Tenant Provisioning

With this approach, deploying a new tenant in a -Tenant model requires modifying only two Git repositories:

  1. Cluster Configuration Repository – Defines infrastructure (EKS, networking, storage).
  2. Cluster Application Configuration Repository – Manages application deployment settings per tenant.

This GitOps-first approach enables:

  • Consistent, repeatable deployments – Infrastructure and application changes are version-controlled.
  • Secure, automated SaaS provisioning – No manual intervention required to onboard new tenants.
  • Scalability at enterprise scale – Hundreds of clusters can be managed with minimal overhead. SaaS

By combining Crossplane, ArgoCD, and Kubernetes, we built a fully automated, GitOps-driven control plane for managing single-tenant SaaS environments—ensuring security, scalability, and operational efficiency at every stage.

 

Final Thoughts

Managing a single-tenant SaaS platform at scale presents significant operational complexity. However, Crossplane and ArgoCD transform this challenge into an automated, self-healing system by extending Kubernetes’ reconciliation model to infrastructure.

By adopting a GitOps-driven approach, we ensure that both infrastructure and applications remain continuously in sync with the desired state—eliminating manual provisioning and minimizing operational overhead. Crossplane provisions and manages cloud resources declaratively, while ArgoCD automates deployments and updates, enabling a seamless multi-cloud control plane.

This architecture provides:

  • Scalability – Infrastructure expands dynamically without increasing complexity.
  • Multi-cloud flexibility – Seamlessly manages workloads across different cloud providers.
  • Operational efficiency – Automates both infrastructure and application lifecycles with minimal intervention.

With Crossplane and ArgoCD, managing hundreds or even thousands of tenant environments becomes a declarative, automated, and scalable process—allowing SaaS providers to focus on innovation rather than infrastructure maintenance.