Skip to main content

Stop Buying a Control-Plane Machine Per Tenant: What Kamaji's Pod-Based Control Planes Actually Save

10 min readDora NodaDora Noda
Share
On this page

Thirty tenants on dedicated control-plane machines cost Clastix's benchmark fleet 90 machines. The same thirty tenants as Kamaji pods cost 3. That 30-to-1 consolidation is the whole pitch for running tenant Kubernetes control planes as pods instead of VMs — and the per-tenant math below shows exactly where it pays, where it doesn't, and what you give up for the discount.

Here is the short version for a Hetzner-priced fleet. One dedicated control-plane box per tenant (a CPX22-class machine at roughly €7.50 a month) costs €225 a month at 30 tenants, €675 if each tenant gets a three-node HA control plane. Thirty Kamaji tenant control planes as pods on a shared management cluster cost on the order of €55 a month all-in — under €2 per tenant. But at 5 tenants the shared management cluster's fixed floor (about €42 a month) loses to five cheap boxes, so Kamaji is not a saving at every scale. The crossover sits around half a dozen tenants against single-box control planes, and at two tenants against HA ones. Everything below earns those three sentences: how Kamaji works, the worked model, where vCluster fits instead, and the isolation catch that actually decides it.

Tenants1 box per tenant (~€7.50/mo)HA: 3 boxes per tenantKamaji on shared management
5~€38/mo~€113/mo~€42/mo — dedicated wins here
30~€225/mo~€675/mo€55/mo (€1.80 per tenant)
100~€750/mo~€2,250/mo€130/mo (€1.30 per tenant)

Bottom line: Kamaji converts the per-tenant control-plane cost from a per-tenant machine into a share of one fixed management cluster plus a small linear pod footprint. The saving is real from roughly six tenants upward and grows with the fleet — but the management cluster is a fixed cost you pay before the first tenant arrives, and sharing it has consequences the catch section below prices honestly.

How Kamaji turns a control plane into pods

Kamaji, the Clastix open-source project, inverts the normal relationship between machines and control planes. Instead of provisioning VMs and installing kubeadm on them, you run a Kamaji operator inside one ordinary management cluster, and each tenant's control plane — its own API server, scheduler, and controller-manager — becomes a set of pods scheduled on that cluster's shared capacity. The tenant's worker nodes can live anywhere: on Hetzner, on Proxmox, on plain VMs joined by hand. Kamaji does not care, because it only owns the control plane half of the problem.

Two custom resources carry the whole model. TenantControlPlane is the stateless definition of one tenant's control plane: version, replicas, resource requests, add-ons. Datastore is a cluster-scoped resource holding the state for one or more tenants — etcd by default, including a kamaji-etcd managed option, with MySQL, PostgreSQL, or NATS available through kine for operators who would rather run a datastore they already know how to back up. Multiple tenant control planes can share one datastore instance, and that sharing is where most of the consolidation comes from: one etcd to operate instead of thirty.

A minimal tenant looks like this:

yaml
apiVersion: kamaji.clastix.io/v1alpha1
kind: TenantControlPlane
metadata:
  name: tenant-acme
spec:
  dataStore: shared-etcd
  controlPlane:
    deployment:
      replicas: 2
      resources:
        apiServer:
          requests:
            memory: 320Mi
            cpu: 100m

Two facts from the project's own documentation set the performance envelope. Tenant control planes come up ready to serve in about 16 seconds, and a version rollout takes about 10 seconds via a blue/green deployment that never serves mixed versions. Those are Clastix's numbers, not independent measurements — treat them as the design target the architecture is built around, which the catch section below then stress-tests. The third integration point is the one that matters for a Cluster API fleet: Kamaji ships a genuine CAPI control-plane provider (cluster-api-control-plane-provider-kamaji), so a tenant cluster becomes a declarative CAPI Cluster object whose control plane just happens to be pods. No bespoke glue, no side-channel provisioning scripts.

The worked cost model: where the saving comes from

Price the two architectures on current Hetzner list prices. A CPX22 (2 dedicated AMD vCPUs, 4 GB RAM) lists around €7.50 a month; a CPX31 (4 vCPU, 8 GB) around €14. The legacy CX22 at €4.49 is on Hetzner's deprecated server-type list — worth knowing because CAPH itself stopped validating hcloudMachine.spec.type against a hardcoded list after Hetzner started retiring types mid-flight, so a MachineTemplate can now fail at the Hetzner API instead of at apply time. Pin your types.

Dedicated control planes are brutally simple to price: one machine per tenant per month, times three for HA. Five tenants cost €38 non-HA or €113 HA; thirty cost €225 or €675; a hundred cost €750 or €2,250. Every tenant pays the full machine whether its API server idles at 2% CPU — and idle tenant API servers almost all idle, which is the entire inefficiency Kamaji arbitrages.

The Kamaji side has a fixed floor and a linear slope. The floor is the management cluster itself: three CPX31-class machines at about €42 a month to host the Kamaji operator, the shared datastore, and monitoring. The slope is the per-tenant pod footprint — roughly half a vCPU and a gigabyte of RAM per tenant control plane all-in once you count the scheduler and controller-manager beside the API server. Thirty tenants add roughly 15 vCPUs and 30 GB of RAM, which fits on one additional shared worker with room to spare: about €55 a month total. A hundred tenants need on the order of 50 vCPUs, a few more workers, roughly €130 a month. The datastore stays near-fixed throughout — Kamaji's own benchmark reconciled 100 tenant control planes against a single shared etcd datastore in about seven and a half minutes, which doubles as a warning about control-plane churn ceilings (more under the catch below).

Read the table at the top again with this model in mind and the shape is obvious: Kamaji loses below about six tenants because the €42 floor exceeds five cheap boxes, ties nowhere in particular, and then wins by a widening margin — roughly 4x at 30 tenants against non-HA, 12x against HA, widening further at 100. The sensitivity variable is tenant count, not workload size, because tenant API servers are idle far more often than tenant workloads are.

Kamaji vs vCluster: full clusters or virtual ones

The comparison every platform team actually runs is Kamaji versus vCluster, and vCluster's own July 2026 comparison post is admirably candid about the difference. vCluster gives each tenant a virtual cluster: a synced-down API surface backed by one shared host control plane, with soft multi-tenancy on shared nodes or hard multi-tenancy via dedicated private nodes. Kamaji gives each tenant a real control plane — a genuine kube-apiserver speaking the full Kubernetes API — with workers that are ordinary nodes joined through standard CAPI infrastructure providers.

That distinction picks the winner by workload shape. If tenants need the full Kubernetes API — their own CRDs, their own admission behavior, version skew between tenants — Kamaji's real API servers are the honest answer, and a virtual cluster's synced API will eventually say no to something a tenant needs. If tenants just need namespaces with guardrails and maximum density, vCluster's shared host control plane packs tighter than one API server per tenant ever will, because there is simply less control plane per tenant to schedule.

What Kamaji does not give you is everything around the control plane. Per-tenant networking, storage classes, workload isolation on shared workers, fleet-wide policy — all still yours to build. vCluster's comparison frames this as DIY fleet management versus a supported platform, which is vendor marketing with a true core: Kamaji is a control-plane engine, not a multi-tenancy platform, and the gap between those two is engineering time you should budget before claiming the machine savings.

The honest catch: sharing the management cluster

Four costs survive the consolidation, and a platform decision has to price all of them.

First, fate-sharing. Every tenant's API server now depends on one management cluster. If that cluster's networking, etcd, or node pool has a bad day, no tenant can reach any control plane — thirty tenants blinded by one incident instead of one tenant blinded by its own. The management cluster is the highest-availability surface in the fleet and must be operated that way: three control-plane nodes, monitored etcd, tested restores, none of which appear in the €55-a-month figure as labor.

Second, the datastore is still etcd, with etcd's failure modes. Thirty tenants sharing one datastore means one tenant's LIST-heavy controller can lean on the same backend serving twenty-nine others, and one corrupted or lost datastore is thirty tenants' state, not one. The 100-tenant benchmark's seven-and-a-half-minute reconciliation time is the other side of the same coin: bulk control-plane churn against a shared store has a throughput ceiling, so fleet-wide upgrades need pacing, not a for-loop.

Third, pod-level isolation between tenant control planes. Tenant API servers share kernels and nodes with each other on the management cluster. For teams, environments, or internal tenants that is a perfectly reasonable trust boundary — arguably better than today's norm of everyone sharing one control plane. For mutually untrusted or hostile tenants it is not hard multi-tenancy, and no amount of network policy changes the shared kernel. Real isolation still means dedicated worker nodes per tenant (which Kamaji supports fine — the control plane being shared never forced the workers to be) plus policy on the management cluster itself.

Fourth, operational DIY. Somebody runs the management cluster, its monitoring (Kamaji ships a ServiceMonitor for exactly this), its upgrades, and the CAPI provider lifecycle. The machine savings are denominated in euros; this cost is denominated in on-call rotations. For a team already running CAPI, the marginal load is small — one more provider, one more cluster to watch. For a team adopting CAPI and Kamaji together, it is a second new system, and the honest sequencing is CAPI first, Kamaji once the tenant count crosses the crossover.

What this means for a Cluster-API PaaS

For a git-push platform on Cluster API, Kamaji slots into one specific growth stage: past the point where per-tenant machines hurt (roughly six-plus tenants, or two-plus tenants wanting HA control planes), before the point where tenant trust levels demand physically separate everything. The CAPI control-plane provider makes adoption incremental — one tenant cluster type among others, reconcilable by the same controllers — rather than a forklift migration. And the isolation analysis cuts in the platform's favor: a PaaS already draws its hard tenant boundary at the workload node pool, so pod-level sharing one layer up, among control planes of tenants whose workloads never meet, fits inside a boundary the platform already enforces.

The isolation question — whether pod-level separation between tenant control planes meets the bar, or only fits tenants who accept softer isolation for a lower price — resolves into tiers, not a verdict. Internal teams and dev/staging environments: Kamaji today, at a tenth of the dedicated cost. Paying tenants with compliance needs: dedicated workers per tenant under Kamaji control planes, keeping most of the saving while restoring the hard boundary where it matters. Actively hostile multi-tenancy: separate management clusters per trust domain, at which point you are back to counting machines and should say so.

None of this replaces the shared-nothing simplicity of one box per tenant at tiny scale. Below half a dozen tenants, buy the boxes — €38 a month is cheaper than a management cluster and operationally invisible. Kamaji is what you graduate to when the tenant count makes the machine-per-tenant tax visible on the invoice, and the table at the top tells you almost exactly when that is.

Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own. Star the repo on GitHub or deploy your first app today.

Related articles

Run this on infrastructure you own

bex is the open-source, AI-native Render alternative — push a git repo and get a running HTTPS service on your own machines.

Get started with bex