k3s vs k0s vs MicroK8s vs Talos: Single-Node Kubernetes on a VPS in 2026
Last month I needed to host a small internal control plane for one of our client projects β nothing fancy, just three services, a Postgres pod, and a job runner. The first instinct was Docker Compose. The second instinct, after a teammate asked “why don’t we just put it on k8s,” was less comfortable: which Kubernetes do you actually pick for a single 2 GB VPS in 2026?
I ended up installing all four serious contenders on identical Hetzner CX22 boxes (2 vCPU, 4 GB RAM, 40 GB NVMe, Ubuntu 24.04) and one Contabo VPS S (4 vCPU, 8 GB RAM) to see what happens once you push them past hello-world. This is the writeup. No marketing claims β only what showed up in htop, kubectl top, and the install logs after about three weeks of poking.
If you came here looking for a one-liner: k3s is still the answer for most VPS operators, Talos is what I’d run if the box only does Kubernetes, k0s is the underrated pick for mixed workloads, and MicroK8s I can no longer recommend because Canonical is sunsetting it in favor of Canonical Kubernetes. Details below.
Why even run Kubernetes on a single VPS?
Across the seven aggregator sites I operate on Hostinger shared and Hetzner VPS, most workloads are tiny. A scheduled importer here, a Next.js front-end there, a Postgres pod, maybe Redis. The honest answer for those is Docker Compose plus systemd. It works, costs nothing, and survives reboots.
Kubernetes earns its keep on a single node only when at least one of these is true:
- You want declarative manifests in Git that match whatever you’ll deploy to a real cluster later (a stepping-stone pattern I use for client work).
- You need self-healing across more than a handful of containers and Compose’s
restart: alwaysisn’t cutting it. - You want Helm, Argo CD, or the broader operator ecosystem (cert-manager, Postgres operators, external-dns) without writing wrapper scripts.
- You’re studying for the CKA/CKAD and want a real cluster, not Minikube.
If none of those apply, stop reading and use Compose. The cheapest VPS that runs Kubernetes comfortably is around $8–$15/month (Hetzner CX22 at €4.59 plus IPv4, Contabo VPS S at $6.99, or DigitalOcean’s 2 GB droplet at $12). On anything smaller than 2 GB RAM you will spend more time fighting the kubelet than running workloads. I tried; it’s not worth it.
The test setup, in one paragraph
Hetzner CX22 in Falkenstein for the primary tests (Ubuntu 24.04 LTS, kernel 6.8, 2 vCPU shared, 4 GB RAM, 40 GB NVMe). Each install was reproduced on a Contabo VPS S in DΓΌsseldorf (4 vCPU, 8 GB RAM, 200 GB NVMe) to confirm the memory numbers weren’t a fluke of Hetzner’s noisy neighbors. All four distros were brought to the same workload: ingress-nginx, cert-manager, a Postgres 16 StatefulSet with a 1 GB PVC, a Next.js Deployment with 2 replicas, and Uptime Kuma for ambient monitoring. I measured idle (no workload), “baseline” (just the cluster components), and “loaded” (with the demo app running).
I also timed installation from a fresh image to kubectl get nodes showing Ready, because installation pain is a real cost when you’re deciding what to run on twelve different VPSes.
k3s: still the default, still the right call
k3s is Rancher’s opinionated Kubernetes distribution, now under SUSE/CNCF stewardship. Single binary, around 70 MB, ships with Traefik, ServiceLB (Klipper), local-path-provisioner, CoreDNS, and Flannel as the CNI. v1.32.x is the current production line as of May 2026; v1.33 is in beta channel.
Install experience
The famous one-liner is still the install:
curl -sfL https://get.k3s.io | sh -
From a fresh Ubuntu image to a Ready node, my stopwatch read 54 seconds on the Hetzner box, including the binary download. kubectl is symlinked, the kubeconfig is at /etc/rancher/k3s/k3s.yaml (mode 600 β chmod it or set --write-kubeconfig-mode 644 at install). If you want to skip Traefik because you bring your own ingress, the install flag is --disable traefik. If you want embedded etcd instead of SQLite for HA later, add --cluster-init.
Memory and CPU
This is the part where I expected Talos to win and didn’t. On the Hetzner CX22, k3s idle (no workloads, only system pods) consumed:
- RSS for
k3s server: ~492 MB - Total cluster RAM (kubelet + containerd + system pods): ~640 MB
- CPU idle: 2–4% steady, with brief 8–12% spikes on the reconciliation loop every 30s
With the loaded workload (Postgres + Next.js + ingress + cert-manager) the cluster sat around 1.1 GB total, leaving 2.6 GB free on the 4 GB box. That’s the number that matters if you’re sizing a VPS plan.
The good
SQLite-backed datastore by default is a real feature, not a downgrade β it removes the etcd footprint entirely on a single node, and the database file (/var/lib/rancher/k3s/server/db/state.db) is trivial to back up with litestream or a nightly sqlite3 .backup. I’ve written about Litestream backups before; pairing it with k3s gives you the cheapest disaster-recovery setup for a Kubernetes control plane I’ve seen.
The bundled local-path-provisioner makes PVCs work out of the box without futzing with CSI drivers, which means a Postgres StatefulSet just runs. ServiceLB lets type: LoadBalancer services bind directly to the node’s IP, no MetalLB required. For a one-VPS setup, these defaults remove three different yak-shaving sessions you’d face on upstream k8s.
The bad
Traefik defaults to v3 now, and the bundled HelmChart CRD for managing it is a SUSE-specific abstraction that doesn’t exist outside k3s. If your team already standardized on ingress-nginx (mine has), you’ll want --disable traefik at install time and never look back. Also: the SQLite datastore is fine for a single node and will work for two, but it isn’t the right choice if you ever expect to scale to three control-plane nodes.
k0s: the quiet alternative for mixed workloads
k0s is Mirantis’s lightweight distribution. Single binary like k3s, but the design philosophy is different: k0s ships with no CNI by default (you pick Kube-router, Calico, or your own), no ingress, no LB, no Traefik. The opinion is that k0s does the control plane, you do the rest.
Install experience
curl -sSLf https://get.k0s.sh | sudo sh
k0s install controller --single
k0s start
From fresh image to Ready: 1 minute 48 seconds, noticeably slower than k3s because k0s downloads the kubelet image, the etcd binary (embedded by default, not SQLite), and runs a self-test before declaring ready. The --single flag is the magic word for VPS use; it skips HA assumptions and runs control plane + worker on the same node.
Memory and CPU
- RSS for
k0s controller: ~412 MB - Total cluster RAM (kubelet + containerd + Kube-router + system pods): ~580 MB
- CPU idle: 1–3%
k0s wins the idle benchmark on my measurements, which lines up with what Portainer and Sidero Labs reported separately. The savings come mostly from a smaller default pod set β no Traefik, no ServiceLB, no local-path-provisioner.
Where k0s pulled ahead
The killer feature I didn’t expect: k0s lets you run all of its components (etcd, kube-apiserver, kube-controller-manager, kube-scheduler) as systemd services, not Pods inside the cluster. That sounds like trivia until you’re recovering a broken cluster on a Saturday night β being able to systemctl restart k0scontroller and watch journalctl is more pleasant than diagnosing a CrashLoopBackOff on the kube-apiserver Pod that’s supposed to fix itself.
It’s also CNCF-conformant in a way that matters more than I initially gave credit for. If you build for k0s on a VPS today and migrate to a managed k8s tomorrow, your manifests don’t change. The same is true of k3s (and Talos), but I’ve had fewer surprises with k0s when copying things back and forth from a dev cluster.
The catch
You bring your own everything. No ingress, no cert-manager, no LB β those are 15 extra minutes of YAML on first install. For folks who’ve done it a few times that’s fine, but if this is your first Kubernetes install on a VPS, k3s is going to feel friendlier.
MicroK8s: the one I’m no longer recommending
I want to like MicroK8s. It’s installed via snap, which means automatic security updates without you doing anything, and the addon system (microk8s enable dns ingress storage) is genuinely nice. On the Hetzner box it idled at around 540–620 MB, depending on which addons were on, which is competitive with k3s and k0s.
The problem is what Canonical announced earlier this year: MicroK8s is being superseded by Canonical Kubernetes, a separate distribution that’s positioned as the new production-grade path. MicroK8s remains supported on LTS channels for the medium term, but the writing is on the wall β new features are landing in Canonical Kubernetes first, and the docs increasingly point at the new product.
If you’re standing up a new VPS today, picking a tool that’s in maintenance mode is the wrong move. Existing MicroK8s deployments are fine to keep running; just don’t start something new on it. Canonical Kubernetes itself is interesting but isn’t single-node-VPS focused yet β its installer assumes you want a real cluster, and the smallest reasonable deployment is currently around 4 GB RAM. I’ll revisit it in a few months when the single-node story matures.
The snap problem
One specific MicroK8s gotcha I hit on Contabo: snap’s automatic refresh tries to upgrade the cluster on its own schedule, which once interrupted a long-running database migration. You can hold the channel with snap refresh --hold, but the fact that you need to is exactly the sort of thing that makes me uncomfortable on a production VPS.
Talos Linux: when the VPS only does Kubernetes
Talos is the wild card. It’s not a Kubernetes distribution β it’s an entire operating system designed to run Kubernetes and nothing else. No SSH (you manage it with talosctl over a gRPC API), no shell to log into, no package manager. The whole OS is immutable, configuration is declarative YAML, and you patch by replacing the rootfs and rebooting.
Install experience
This is where Talos gets weird for VPS users. Most VPS providers boot from their own ISO, not yours, so you can’t just hand them a Talos image. The workable paths are:
- Hetzner Cloud: there’s a community installer that uses rescue mode plus
ddto write Talos to the disk. Works, takes about 8 minutes. - Equinix Metal / Latitude.sh / OVHcloud Bare Metal: these support custom iPXE and Talos is officially documented.
- Contabo, DigitalOcean, Vultr: realistically, no. You can hack it but it’s not a sane production path.
On Hetzner I went from rescue boot to Ready node in 9 minutes 12 seconds, most of which was waiting for the post-dd reboot.
Memory and CPU
- Total system RAM (entire OS plus Kubernetes): ~520 MB
- CPU idle: 1–2%
- Disk footprint of the OS image: ~150 MB
Because Talos isn’t fighting Ubuntu’s systemd, journald, snapd, cloud-init, unattended-upgrades, and a couple dozen other services for memory, it really does come in lower. The numbers from Sidero Labs’ own benchmarks lined up with what I saw.
What Talos is great at
Security posture is the headline. There’s no SSH to brute-force, no shell to drop into via a container escape, no package manager to compromise. The attack surface is the Kubernetes API server (which you can lock down with network policies and OIDC) and the talosctl API (which uses mutual TLS by default). For client projects under compliance review, this is a genuine value-add.
Upgrades are atomic. talosctl upgrade swaps the rootfs to a new immutable image and reboots. If it boots, great. If it doesn’t, the previous image is still there and a rollback is one command. I’ve broken more Ubuntu boxes during routine upgrades than I have Talos clusters, even though I’ve run far more Ubuntu.
What Talos is bad at
The cost is rigidity. If you wanted to also run tailscale on the host, or a Postgres backup script outside of Kubernetes, or anything that isn’t a Kubernetes Pod β you can’t. Everything must be a Pod. For my 7 aggregator sites, where I sometimes need a quick cron job that’s a single bash script, that’s a constraint I’m not willing to take on shared infrastructure.
If, however, you have a VPS that exists solely to run Kubernetes workloads and you don’t need shell access for anything, Talos is the technically correct choice.
Head-to-head, single-node VPS comparison
| Metric | k3s v1.32 | k0s v1.32 | MicroK8s 1.32 | Talos v1.9 |
|---|---|---|---|---|
| Install to Ready | ~54 s | ~1 m 48 s | ~2 m 30 s | ~9 m (Hetzner) |
| Idle RAM (cluster only) | ~640 MB | ~580 MB | ~620 MB | ~520 MB (entire OS) |
| Loaded RAM (demo workload) | ~1.1 GB | ~1.05 GB | ~1.15 GB | ~1.0 GB |
| Default datastore | SQLite | etcd (embedded) | dqlite | etcd |
| Default CNI | Flannel | None (BYO) | Calico | Flannel |
| Default ingress | Traefik | None (BYO) | nginx (addon) | None (BYO) |
| Default LB | ServiceLB | None (BYO) | MetalLB (addon) | None (BYO) |
| Auto updates | Manual | Manual | Snap (channel) | talosctl upgrade |
| VPS provider support | Universal | Universal | Universal | Limited (custom ISO) |
| Steward | SUSE / CNCF | Mirantis | Canonical (sunset) | Sidero Labs |
| License | Apache 2.0 | Apache 2.0 | Apache 2.0 | MPL 2.0 |
The numbers are within rounding noise on a real workload. The differentiators are install pain, defaults, and the steward’s future direction.
Which one I picked, and why
For the client control plane I mentioned at the top, I picked k3s. Three reasons, all boring:
- The install was already done before lunch, including ingress-nginx swapped in for Traefik and cert-manager wired up.
- SQLite + Litestream gave me a backup story I trusted on day one, without standing up a separate etcd backup pipeline.
- If the client outgrows it, the migration path is well-trodden β k3s exports plain Kubernetes manifests that move to any conformant cluster.
For a personal CKA study cluster I’m setting up next week, I’m going with k0s, specifically because it forces me to install the CNI, ingress, and LB myself. That’s the muscle memory the cert wants you to build.
For the read-only documentation aggregator I’m considering self-hosting (still on the maybe pile), I’d use Talos on a Hetzner box. The workload is 100% Kubernetes, nothing else, and the upgrade story is more pleasant than babysitting apt.
I’m not starting anything new on MicroK8s. Not because it’s bad β it works fine β but because committing to a maintenance-mode distribution for a system you’ll run for years is asking for migration pain later.
The honest caveats
A few things I’d want a friend to know before they spin any of this up:
Single-node Kubernetes is not HA. If the VPS dies, your cluster dies with it. Nothing in this article changes that. For real HA you need at least three nodes spread across providers or availability zones, and at that point the comparison shifts.
RAM headroom matters more than CPU. All four distros are CPU-cheap when idle. The thing that kills you on a 2 GB VPS is OOM-killer ending your Postgres pod because the cluster components ate 700 MB and your app needed 1.4 GB. Plan for 1.5× what you think you need.
Backups are not optional. Whatever you pick, on day one set up an etcd snapshot (or SQLite backup for k3s) to off-VPS storage. Hetzner Storage Box, Cloudflare R2, Backblaze B2 β pick one and automate it. I cannot count how many self-hosted clusters I’ve seen lose state because the operator assumed RAID was a backup.
Ingress is where the time goes. On every fresh install, expect to spend 30–60 minutes on ingress-nginx + cert-manager + DNS plumbing before your first HTTPS-fronted service is up. The Kubernetes part is easy; the DNS-and-TLS part is where I always burn an hour.
FAQ
Can I run Kubernetes on a 1 GB VPS?
Technically yes with k3s or Talos, practically no. You will spend more time tuning the OOM-killer and reserving memory than running workloads. Start at 2 GB minimum, 4 GB is the comfortable floor.
Is k3s production-ready?
Yes. It’s CNCF-certified, has been in production at companies running 10,000+ node clusters, and is the default for both Rancher and Fleet. Single-node k3s is a supported topology, not a hack.
What about k3d, kind, or minikube?
Those are dev/test tools that run a cluster inside Docker. They’re excellent for local laptops but not designed to host production workloads on a VPS. The Kubernetes API will look identical; the operational story doesn’t.
Does RKE2 belong in this comparison?
RKE2 is k3s’s sibling, also from SUSE, hardened for FedRAMP/STIG compliance. On a single-node VPS it adds overhead without giving you the compliance benefits. Skip it unless you specifically need the hardening profile.
What CNI should I pick if k0s makes me choose?
Kube-router is the default and works fine. Calico if you want network policies that integrate with anything else. Cilium if you’re building toward eBPF observability β but Cilium pushes RAM usage up by ~150 MB, so factor that into your VPS sizing.
Closing notes
The honest reality of single-node Kubernetes on a VPS in 2026 is that any of these four (well, three) distributions will run your workload. The differences I’d optimize for are operational, not technical: who maintains the project, how do upgrades work, how do you back it up, and how do you recover when something breaks at 2 a.m. on a Sunday.
My ranked recommendation, for the median VPS operator running mixed workloads on Hetzner, Contabo, or similar: k3s first, k0s second, Talos third if your VPS provider supports it, MicroK8s avoided for new deployments. That ordering hasn’t changed for me in two years of running variations of this exercise, and I don’t expect it to change in the next twelve months unless Canonical Kubernetes ships a credible single-node story.
If you’re weighing this against not running Kubernetes at all β Compose plus systemd remains a fine answer for under a dozen containers, and there’s no shame in that path. Pick the smallest tool that solves your problem; Kubernetes earns its complexity only when you actually need what it offers.
Found this helpful?
Subscribe to our newsletter for more in-depth reviews and comparisons delivered to your inbox.