← Back to Blog

The Kaja Team

A cluster with no public IP, and what still works

We took a two-node cluster with nothing but RFC1918 addresses and published a site on it over HTTPS. Here is each step, what it required, and the parts that are genuinely a trade.

The claim that a cluster does not need a public IP is easy to write and hard to check. So this post is one run, with the addresses and the response codes, on a cluster that has no route in from anywhere.

The cluster is two nodes of k3s under k3d, on a laptop. Its load balancer addresses are 172.18.0.3 and 172.18.0.4. Those are RFC1918: not routable on the internet, not forwarded by anything, and behind a home router doing NAT. There is no port forwarding and no VPN. A laptop is not a datacentre, and that is the point of choosing it: if it works here it works in a rack nobody can reach.

Connecting it

Connecting a cluster is one command that installs cert-manager and an agent. The agent opens a connection outward to the control plane and holds it open. Nothing is opened inbound, no kubeconfig leaves the machine, and no cloud account is involved, because there is no cloud account here to involve.

The console reported the cluster connected on the first poll after the install finished.

Publishing something on it

We deployed WordPress from a template, which also provisions a managed MySQL and wires the app to it. That path uses public images, so it needs no registry credentials and no Git provider connected. From an empty workspace to a running site was about ten minutes, most of it spent waiting for MySQL to accept connections.

The site answered on a generated hostname under the cluster's own subdomain:

$ curl -o /dev/null -w '%{http_code} %{ssl_verify_result}' https://wordpress.<cluster>.apps.kaja.dev/
302 0

A 302 to the installer, and ssl_verify_result: 0, which is curl reporting that the certificate chain validated. The certificate was issued by Let's Encrypt for that hostname. Nothing about the cluster changed to make this happen: the request arrives at a gateway, and travels back down the connection the cluster already opened.

What this costs

Three things are worth stating rather than discovering later.

The gateway terminates TLS, so it sees that traffic in the clear on its way through. That is the price of publishing from a network with no inbound route, and it is why the behaviour is opt-in per cluster. A cluster that does have a public address serves its own traffic directly and the gateway is never in the path.

Your compute is still yours to run. Nothing here creates a cluster, a node or a load balancer for you. You bring a cluster; the platform operates what runs on it.

And this was a test cluster we built to check a property, then deleted. It is not evidence that anyone runs production this way, because nobody does yet.

Why the requirement is the interesting part

Most platforms that deploy into infrastructure you own connect inward: they need to reach your Kubernetes API server, and they need your cluster to be able to obtain a public address for a load balancer. Both are documented requirements you can go and read in their own docs, and on a mainstream cloud account both are satisfied without thinking about it.

The requirement only becomes visible when the cluster is somewhere else: a customer's datacentre, a retail site, a hospital network, a machine behind CGNAT. The useful question when comparing platforms is not which is fastest, it is which ones can be pointed at the infrastructure you actually have.