The word "multi-tenancy" gets used to mean a lot of different things. At the minimal end, it means "multiple teams share a Kubernetes cluster." At the full end, it means "multiple organisations with legally separate data and compliance requirements operate on the same physical infrastructure, with cryptographic guarantees that their workloads cannot interact." The gap between those two definitions is enormous โ and most platforms that claim multi-tenancy are firmly at the minimal end.
This article describes what real multi-tenancy requires, why it matters, and how AravaliStack implements it from the network layer up to the billing dashboard.
Why application-layer isolation is not enough
The most common multi-tenancy pattern in Kubernetes is namespace isolation: each team or tenant gets a namespace, RBAC rules prevent them from accessing each other's resources, and a ResourceQuota limits how much compute they can consume. This is a reasonable starting point. It is not sufficient for regulated environments.
Here's why: Kubernetes namespaces are a logical construct. The network is shared. By default, any pod in any namespace can send a TCP packet to any other pod in any other namespace. The application isn't supposed to โ but the network doesn't prevent it. For a hospital system where Tenant A is a cardiology department and Tenant B is an oncology department, "the application isn't supposed to" is not an acceptable isolation guarantee.
Layer by layer: what real isolation looks like
Network isolation
AravaliStack enforces network isolation using Kubernetes NetworkPolicy (enforced by Calico or Cilium). Every namespace has a default-deny policy applied at creation: no ingress or egress is permitted unless explicitly allowed. Tenants must declare every network dependency โ which services they call and which services can call them โ and those declarations are reviewed before being applied.
For the highest-sensitivity deployments (defence, classified environments), we extend this to VLAN segmentation at the physical network layer โ namespace-to-VLAN mapping, enforced by the CNI plugin. Traffic between classification levels requires explicit cross-domain guard configuration.
Compute isolation
Shared node pools are fine for most tenants. For tenants that require hardware-level isolation โ either for security (confidential compute) or performance (guaranteed GPU allocation) โ AravaliStack supports dedicated node pools with Kubernetes taints and tolerations. A tenant's workloads only run on nodes labelled for them; other pods are rejected by the scheduler.
Storage isolation
Every tenant gets separate Persistent Volumes provisioned from separate storage classes. The storage class for a regulated-data tenant uses encryption-at-rest with a tenant-specific encryption key, managed by Vault. Tenant A's data cannot be read by Tenant B even with direct storage access โ the keys are different, and both are managed by Vault with per-tenant access policies.
Identity isolation
Keycloak is configured with a realm per tenant (or per tenant group, depending on isolation requirements). Each realm has its own users, groups, roles, and SSO configuration. A user authenticated in Tenant A's realm has no identity in Tenant B's realm โ the identity providers are completely separate. Ory Keto's permission system enforces that resources owned by Tenant A cannot be accessed by Tenant B's identities, regardless of what permissions they claim.
Secrets isolation
Vault uses a namespace-per-tenant model (Vault Enterprise) or separate secret mount paths per tenant. A service in Tenant A's namespace can only request secrets under the Tenant A path in Vault. The Vault policy that governs this is managed through GitOps and is audited at every change.
The billing layer: often forgotten, always contentious
Here is the layer that most multi-tenant platforms omit entirely: billing. If tenants share infrastructure, who pays for what? In most enterprise Kubernetes deployments, the answer is "it comes out of a shared IT budget and nobody knows the breakdown." This causes two problems.
The first is financial: teams that over-consume pay nothing extra, which eliminates any incentive for cost-efficient engineering. The second is audit: for MSPs deploying AravaliStack for external clients, the inability to produce accurate per-tenant usage invoices is a business-critical problem.
AravaliStack's cost layer uses OpenCost for per-namespace resource attribution โ every CPU-hour, every GB-hour of storage, every GB of network egress is measured and attributed to the namespace it was consumed in. This data is available in real-time through the cost dashboard and through the Lago-compatible billing API. MSPs can generate per-tenant invoices directly from the platform's usage data.
The governance layer: who can change what
Multi-tenancy is not just technical isolation โ it is also governance isolation. Tenant A's platform administrator should not be able to modify Tenant B's namespace policies. The platform operator (the MSP or central IT team) should be able to see everything but modify only platform-level configuration, not tenant-level application state.
AravaliStack implements this through a three-level RBAC hierarchy:
- Platform operator. Full cluster-admin access to platform infrastructure (CNI, storage classes, node pools, Vault configuration). Cannot modify tenant application state.
- Tenant administrator. Full access to their namespace(s). Cannot see other tenants' namespaces or modify platform infrastructure.
- Tenant developer. Read/deploy access to their team's namespace. Cannot modify RBAC, network policies, or resource quotas.
These roles are defined in Git, applied by Flux, and audited in Vault's access log. No role escalation is possible without a Git PR and a platform operator approval.
Multi-tenancy done right is hard. It requires decisions at seven different layers of the stack, each of which adds complexity that must be managed. But for the class of enterprises AravaliStack serves โ regulated, multi-team, often multi-client โ the alternative is either a separate cluster per tenant (which is operationally untenable at scale) or inadequate isolation (which is a compliance liability). The architecture we've described is the third path.
