Tech Blog by vClusterPress and Media Resources

Understanding Kubernetes Multi-Tenancy: Models, Challenges, and Solutions

Feb 27, 2025
|
min Read
Understanding Kubernetes Multi-Tenancy: Models, Challenges, and Solutions

Kubernetes was designed for efficient resource sharing, but complexity escalates when multiple teams or users step into the same cluster. As organizations scale, the challenge isn't just about running workloads; it's about how those workloads coexist securely and efficiently.

Daniele Polencic from LearnK8s recently broke this down, diving deep into the isolation models, their limitations, and the tooling that makes multi-tenant environments manageable. If you want the full technical breakdown, watch the session.

Kubernetes as a Shared System

To understand multi-tenancy, we must first understand how Kubernetes processes a request. When a user runs `kubectl apply` to create a Deployment, the API Server takes control. It validates the request, runs authentication and authorization checks, and commits the Deployment manifest into etcd.

The Deployment controller inside the `kube-controller-manager` picks up the change, creates a corresponding ReplicaSet, and ensures the desired number of pods exist. The ReplicaSet controller watches for changes, spawns pods accordingly, and registers them in etcd. The kube-scheduler steps in, scanning for unscheduled pods. It evaluates available nodes, selects the best fit, and assigns the pod.

Still, no workloads are running; only metadata exists. The real action begins when the kubelet, running on each worker node, detects a new pod scheduled to its node. It pulls the pod specification from the API server, preps the runtime, and finally launches the containers.

At no point does Kubernetes distinguish between teams or users. Every request passes through the same API server, every resource lands in the same etcd, and every kubelet treats pods the same way.

The reason is Kubernetes is a shared system.

In a multi-tenant cluster, the challenge of this shared infrastructure is that every team's workloads flow through the same control plane.

The API server doesn't care who owns a resource.

The same applies to etcd—there's no inherent separation of data. The scheduler and kubelets don't make distinctions either. When you run `kubectl get deployments`, and you'll see deployments from every team.

But what if you don't want to share?

Introducing Multi-Tenancy in Kubernetes

One approach would be hardcoding tenancy into the API itself, defining scoped endpoints like `/api/team-a` and `/api/team-b`, where each team only sees their resources. Kubernetes achieves this dynamically with Namespaces and RBAC (Role-Based Access Control).

Namespaces create logical boundaries at the API level. When a user in Team A runs `kubectl get pods,` they only see their namespace's pods. In addition, RBAC defines who can access what, ResourceQuotas prevent noisy neighbors from over-consuming shared infrastructure, LimitRanges enforce per-tenant resource constraints, NetworkPolicies segment traffic, and Pod Security Admission restricts unsafe workloads.

But even with all that, Namespaces doesn't isolate workloads. They are just a control mechanism for permissions and API scoping.

Building True Multi-Tenant Platforms

When running a multi-tenant Kubernetes platform, you need all these components working together. You need a framework that expresses tenancy as a single specification like Capsule. Instead of manually configuring quotas, roles, and network policies for every team, Capsule lets you define tenancy in one place.

It's one of the first tools that makes Kubernetes namespaces functional in a multi-tenant environment. Hierarchical Namespace Controller extends namespace capabilities further, while Kubesphere takes a broader platform approach.

However, namespaces have limitations.

Some objects like PersistentVolumes, nodes, Custom Resource Definitions (CRDs), even namespaces themselves aren't bound to a single namespace.

How do you scope them to a specific team? RBAC grants access, but it doesn't partition resources dynamically.

The solution is API proxies.

Tools like Capsule Proxy and KCP sit in front of the real API server as a proxy layer, impersonate users, and filter responses. The control plane  remains shared, but tenants only see their own resources. For example, an admin sees all PersistentVolumes, but a tenant only sees their assigned ones. [A team at Apple](https://www.youtube.com/watch?v=dQ4j5V6lqeo) followed a similar API Server as a Service model but took a unique approach by fully abstracting the Kubernetes API server for tenants. Instead of running a single shared API or filtering access via proxies, they create tenant-scoped workspaces where each team interacts with its own virtualized API layer. However, even this approach doesn't solve the CRD isolation problem.

CRDs are tricky; they live in etcd, and etcd is shared. You can't install two versions of the same CRD in a single cluster.

Similarly, you can't create CRD-level isolation without splitting etcd.

Then, there's the problem of node isolation. You can restrict CPU and memory and enforce network policies, but you can't isolate I/O. If a database runs on a node with noisy neighbors, they compete for disk throughput. You can't isolate network bandwidth at the node level, either.

Namespaces weren't designed to give a real multitenancy. And if you're trying to isolate CRDs, you hit the same roadblock—shared control plane, shared etcd, shared infrastructure.

So how do we fix this?

If isolating the database is too complex, isolate the control plane instead.

Instead of running a single control plane for every team, give each tenant a dedicated API server and an isolated etcd instance.

Teams can run different CRD versions without conflicts, workloads are decoupled, and tenancy becomes a first-class concept. The challenge isn't in the idea—it's in the execution.

Achieving Hard Isolation: Control Plane Strategies  

There are three major approaches to hard separation at the control plane level, each with its own trade-offs.

The first approach is simple: dedicated clusters for each team. Every team gets its own cluster, fully isolated, with separate control and data planes. However, managing these clusters at scale is a different challenge. You need a way to orchestrate deployments across them, distribute workloads efficiently, and interconnect networking, storage, and I/O.

Tools like KubeAdmiral, Karmada, Sveltos, Kubesphere, and Kubeslice come in here. They solve the problem of multi-cluster workload distribution by ensuring that applications, policies, and networking remain synchronized across independent clusters. Karmada, for instance, deploys a cluster manager that installs control planes and agents in each target cluster and creates an abstraction that ties them together.  

The second strategy is nesting control planes inside a single manager cluster.

Instead of running separate clusters, you package the entire Kubernetes control plane as a pod inside an existing cluster.

Like managed Kubernetes services on AWS, GKE, or AKS, you attach worker nodes directly to the control plane. The architecture shifts the burden of worker node management onto the teams using the cluster. They provision their own virtual machines, attach them to their assigned control plane, and run their workloads independently. You have one cluster running multiple encapsulated control planes as pods, with worker nodes dynamically assigned. Nested control planes work well for managed services.

If a node breaks, it's the tenant's problem, as they own the infrastructure they attach. The tools making this possible are Kamaji, HyperShift from Red Hat, vCluster Pro, and Kosmotron from Mirantis.  

Take Kamaji, for example. It starts with a management control plane. When a team needs a cluster, you spin up a new pod—inside that pod is a fully functional Kubernetes control plane. The team provisions its nodes, installs kubelet, and attaches them to their new control plane. At that point, they have a fully isolated Kubernetes environment.

If another team needs a cluster, the same pattern repeats: they launch a new control plane pod, attach nodes, and deploy workloads. It's a self-service multi-tenancy model with full API server isolation.  

The third approach is having single-cluster control planes without external nodes. Instead of spinning up control planes as pods in an external management cluster, everything stays inside one cluster. The control planes don't have their own nodes; instead, they synchronize resources back to the main cluster.

How vCluster Delivers Tenant Cluster Isolation

vCluster's architecture separates the Kubernetes control plane from the underlying compute, giving each tenant their own API server, etcd, RBAC, and CRDs without provisioning a separate physical cluster.

When a tenant deploys a pod inside their vCluster tenant cluster, the request hits their isolated API server. A component called the syncer then maps that workload down to the host cluster, where it runs on real nodes. From the tenant's perspective: they have cluster-admin access, full RBAC control, and a complete Kubernetes environment. From the operator's perspective: the compute is shared, but the control plane is fully isolated.

This is not soft tenancy. Control plane isolation in vCluster means:

  • No shared etcd. Each tenant cluster has its own isolated etcd — tenants cannot see or affect each other's cluster state.
  • No CRD conflicts. Each tenant installs their own operators, CRDs, and webhooks without interfering with other tenants. Critical for GPU-heavy environments where the NVIDIA GPU Operator and custom schedulers are common.
  • No RBAC bleed. Each tenant is cluster-admin of their own environment. They cannot access other tenants' resources, even by misconfiguration.

For workloads requiring stricter compute isolation, vCluster supports:

  • Private nodes — dedicated GPU nodes assigned to specific tenant clusters
  • vNode — kernel-native workload isolation (seccomp, cgroups, AppArmor) without hypervisor overhead

CoreWeave, Nscale, and 50+ other GPU cloud and Fortune 500 customers run this architecture in production across 100K+ GPU nodes.

Evaluating Multi-Tenancy Approaches

Multi-tenancy in Kubernetes isn't just about picking a tool but understanding the trade-offs. Every approach has its limits, and the landscape isn't balanced.  

Dedicated clusters are the cleanest solution, primarily when operating across multiple clouds or regions. Full isolation, no shared resources, no tenant conflicts. But not every team needs that level of separation, and managing fleets of clusters adds complexity.  

Control plane as a service works well for managed Kubernetes providers. Spinning up dedicated control planes per tenant makes sense if you're offering Kubernetes as a service. But unless that's your business model, the use case is limited.  

That brings us to the real contenders—Capsule, vCluster, and native Kubernetes namespaces. They don't require fully custom infrastructure, they scale without breaking core Kubernetes workflows. Of these, vCluster occupies a distinct position: it provides full control plane isolation (dedicated API server and etcd per tenant) without requiring a separate physical cluster, and pairs that isolation with a range of hardware-level options — shared nodes, private nodes, or vNode kernel-native isolation — that namespace-based tools cannot match. This makes it particularly suited for GPU cloud operators and AI infrastructure platforms where tenants need cluster-admin access, custom CRDs, and hardware isolation options at scale.

Making the Right Tradeoffs

Multi-tenancy isn't a single feature. It's a range of solutions, each trading off isolation, complexity, and cost.

Most teams start with namespaces. It's simple, familiar, and works for basic segmentation. But you need more when you need isolation beyond API boundaries—when teams require their own CRD versions, or when workloads compete for storage, network, or I/O.

Capsule brings structure and control to namespaces. vCluster virtualizes control planes, allowing teams to run different CRDs. If more profound isolation is required, you move to dedicated control planes and eventually separate clusters.

At the far end of the spectrum, you're building custom platforms—integrating networking, storage, and security across multi-cluster or multi-region deployments.

So how do you decide where to stop?

There's no single answer. Each approach comes with tradeoffs.

Kubernetes was designed for sharing. The isolation question is how much separation you need — and at which layer.

For most teams, namespaces, quotas, and RBAC are sufficient. For platforms serving multiple customers, or GPU infrastructure where tenants need independent operators and hardware guarantees, control plane isolation is the answer.

vCluster delivers control plane isolation — dedicated API server and etcd per tenant — at the operational cost of namespaces, not physical clusters. That's the architecture that GPU cloud operators use to run hundreds of isolated tenant environments on shared GPU infrastructure without the overhead of managing a fleet of physical clusters.

If you're building infrastructure for multiple tenants on GPU hardware, see how vCluster works for AI cloud providers →

Share:
Get started with the #1 tenant isolation platform.

Give your tenants the hyperscaler experience, ready in seconds.

Ready to take vCluster for a spin?

Deploy your first virtual cluster today.