Compare K3s, upstream Kubernetes and MicroK8s on footprint, datastores, HA and updates, and pick the right fit for edge, dev or production.
Your team wants Kubernetes on a fleet of small edge devices, each with 512MB of RAM. Upstream Kubernetes control-plane components alone will not fit there. So you look at "lightweight Kubernetes", and find three options that solve overlapping but different problems. Pick the wrong one and you re-architect the fleet in six months.
K3s, upstream Kubernetes (K8s) and MicroK8s all expose the same Kubernetes API. They differ in packaging, datastore, update model and what they assume about your environment. Those differences, not feature checklists, should drive the decision.
K8s is the upstream project you assemble yourself, K3s is a single-binary distribution built for small and remote environments, and MicroK8s is a snap-packaged distribution built for low-touch setup. All three are conformant Kubernetes, so workloads move between them.
In short, K3s assumes you deploy somewhere hard to reach and want minimal moving parts. MicroK8s assumes you want the lowest-touch path to a working cluster and accept snap. Upstream K8s assumes you want full control and have a team to operate it.
K3s agent nodes are the clear footprint winner, while server-node requirements are closer than most comparisons suggest. K3s documents about 512MB for an agent and about 2GB with 2 CPUs for a server. kubeadm's documented minimum for a control-plane node is also about 2GB and 2 CPUs.
The real differences are elsewhere:
This also clarifies the 512MB case. Those devices run K3s as agents, and the control plane lives on a larger machine elsewhere. Always check each project's current requirements, and leave headroom for your own workloads, because the documented minimum is not a comfortable operating point.
K3s installs with one command, MicroK8s installs as a snap, and upstream Kubernetes has no single-command path: you install a container runtime and the kubeadm tools first, run kubeadm init, and then install a CNI plugin.
## K3s: single server, pinned to a versioncurl -sfL https://get.k3s.io | \ INSTALL_K3S_VERSION=<version> sh - ## K3s: join an agent to that servercurl -sfL https://get.k3s.io | \ K3S_URL=https://server.example.net:6443 \ K3S_TOKEN=<node-token> sh - ## MicroK8s: install from a pinned channelsudo snap install microk8s --classic --channel=<version>/stablesudo microk8s enable dns ingress hostpath-storageUpstream takes more steps, and the order matters:
## 1. install containerd, kubelet, kubeadm and kubectl first## 2. create the control planesudo kubeadm init --pod-network-cidr=10.244.0.0/16 ## 3. install a CNI (nodes stay NotReady until you do)## 4. join workers with the command kubeadm init printedThe pod CIDR must match what your chosen CNI expects, so read the CNI's install guide before you run kubeadm init.
Piping a script into a shell is convenient but risky. For production, download the installer, review it, and pin the version, or use your configuration management tool.
K3s reads its settings from a config file, which keeps installs reproducible:
cluster-init: truedisable: - traefiksecrets-encryption: truewrite-kubeconfig-mode: "0640"K3s bundles Traefik as its default ingress, plus a service load balancer (ServiceLB), local-path storage and metrics-server. Disable the ones you do not want, or you may end up running two ingress controllers.
K3s offers three datastore modes, MicroK8s uses dqlite, and upstream uses etcd. The choice decides how you survive losing a control-plane node.
--cluster-init and join two more, for a three-server HA control plane.microk8s add-node to join.Use three servers, not two. Embedded etcd needs a majority of members alive, so two servers tolerate no failure at all, while three tolerate one.
If you may need HA later, decide before you deploy. Check the K3s documentation for the supported path to move from SQLite to embedded etcd, and test it before you rely on it.
MicroK8s requires snapd, and snap applies updates automatically unless you control them. That is the detail that decides adoption before any feature comparison.
If your hosts use a hardened or minimal image without snapd, MicroK8s is not an option. If you can use it, install from a specific channel (such as a Kubernetes minor version) so a refresh does not jump you to a new minor release, and use snap's refresh controls to schedule or hold updates during sensitive periods.
## track a minor version channel, then control refresh timingsudo snap refresh microk8s --channel=<version>/stablesudo snap refresh --hold=720h microk8sBack up the datastore on a schedule and upgrade one node at a time. The commands differ by distribution, and a common mistake is using the etcd snapshot command on a K3s server that runs SQLite.
## K3s with embedded etcd: snapshot, then listsudo k3s etcd-snapshot save --name nightlysudo k3s etcd-snapshot ls ## K3s with default SQLite: copy the database file insteadsudo cp /var/lib/rancher/k3s/server/db/state.db /backup/For K3s upgrades, the system-upgrade-controller applies new versions through a Plan resource, draining nodes in order. For kubeadm, you run kubeadm upgrade plan and kubeadm upgrade apply on the first control-plane node, then kubeadm upgrade node on the others. For MicroK8s, you control timing through snap channels and refresh holds as shown above.
Match the tool to the environment, not to a feature list.
For local development on a laptop, kind or minikube are also common choices. If you want an immutable, API-managed operating system under the cluster, Talos Linux is worth evaluating as well.
Footprint and installation:
| Factor | K3s | MicroK8s |
|---|---|---|
| Packaging | Single binary | Snap |
| Install dependency | None | snapd |
| Default datastore | SQLite | dqlite |
Self-managed options for larger platforms:
| Factor | kubeadm (upstream) | RKE2 |
|---|---|---|
| Assembly | You choose each part | Bundled and tested |
| Datastore | etcd, you manage it | Embedded etcd |
| Hardening | Your responsibility | Hardened defaults |
RKE2 gives you the same conformant Kubernetes with security-focused defaults, which makes it the usual step up from K3s when compliance matters. kubeadm gives the most control and the most work.
For edge, IoT or any site where remote access is unreliable, K3s is the default recommendation. It is conformant, light and simple to automate.
k3s etcd-snapshot save on a schedule (or copy the SQLite file) and copy backups off the node, then practice a restore.For production at multi-tenant scale, use a managed service unless you have a dedicated platform team and a specific reason not to. For local development on Ubuntu, MicroK8s is a good fit once you have confirmed snapd is available and permitted.
References and Further Reading
- K3s Documentation - Requirements, HA and datastore options
- MicroK8s Documentation - Snap channels, add-ons and clustering
- Creating a Cluster with kubeadm - Upstream install reference
- RKE2 Documentation - Hardened distribution for stricter environments
As an agent node, yes: K3s documents 512MB as the agent minimum. The control plane (server) needs more, around 2GB per the docs, so small devices join a server running elsewhere. Leave headroom above the minimum, because your workloads and the OS also need memory.
For a single server node with any number of agents, it can be, as long as you accept that the control plane is a single point of failure. For a highly available control plane you need embedded etcd (start with --cluster-init on three servers) or an external database such as PostgreSQL or MySQL. Back up the SQLite file directly, because etcd-snapshot only covers embedded etcd.
It runs on Linux distributions that support snap, so snapd must be installed and allowed. Hardened or minimal images that remove snapd rule it out. Also plan for snap's automatic refreshes by tracking a channel and controlling when updates apply.
No. K3s is a CNCF-certified Kubernetes distribution that passes the upstream conformance tests. It removes or replaces some in-tree and optional components and bundles others (containerd, Flannel, CoreDNS, Traefik, a service load balancer and local-path storage by default), so check which defaults you want to keep.
Usually not. A managed service (EKS, GKE or AKS) handles the control plane, upgrades and etcd. Self-manage only with a dedicated platform team and a clear reason, such as strict data residency, air gaps or custom control-plane settings, and consider a hardened distribution like RKE2.
Discussion0