Kubernetes Ecosystem: From User to Contributor, Episode 1
← Kubernetes: From Borg to Platform Engineering · EP01: MicroK8s Explained · All Kubernetes Ecosystem Episodes →
11 min read
TL;DR
- What is MicroK8s? A full, CNCF-conformant Kubernetes cluster packaged into a single snap package — install and have a running cluster in under 60 seconds, no separate container runtime or CNI install required
- Built by Canonical for edge, IoT, and ephemeral CI clusters, where minimal footprint and single-command lifecycle matter more than fine-grained tuning
- Add-ons (
dns,storage,ingress,metallb,cilium,gpu) replace what you’d otherwise hand-install and wire together yourself - High-availability mode uses Dqlite (a distributed, Raft-backed SQLite) instead of etcd — a deliberate design choice with a real operational trade-off
- The same “just works” install model that makes MicroK8s fast to stand up also hides some of the control-plane tuning knobs production operators expect from etcd
- Contribution opportunity: Dqlite’s operational tooling is years behind etcd’s — a real, specific, achievable gap, covered in depth below
The Big Picture
TRADITIONAL KUBERNETES INSTALL MICROK8S INSTALL
───────────────────────────── ──────────────────
Install a container runtime $ sudo snap install microk8s --classic
Install kubelet, kubeadm, kubectl $ microk8s status --wait-ready
Stand up and configure etcd
kubeadm init, join workers │
Install a CNI plugin ▼
Install an ingress controller One snap install =
Install a storage provisioner kubelet + kube-apiserver + kube-scheduler
Wire it all together, hope + kube-controller-manager + containerd
the versions are compatible + Dqlite + CNI (via add-on)
— one running cluster, one command
What is MicroK8s? It’s Canonical’s single-binary distribution that packages an entire Kubernetes control plane and node into one snap package, so snap install microk8s produces a running, CNCF-conformant cluster without a separate container runtime, etcd install, or CNI setup step. The trade for that speed is control: the same bundling that removes a dozen manual steps also removes a dozen places you’d normally tune something.
How MicroK8s Fits an Entire Cluster Into One Snap
A snap package is a self-contained, confined Linux application bundle — MicroK8s ships its own containerd, its own CNI defaults, and its own datastore inside that bundle, rather than expecting the host to provide them.
$ sudo snap install microk8s --classic
microk8s (1.29/stable) v1.29.1 from Canonical✓ installed
$ microk8s status --wait-ready
microk8s is running
high-availability: no
datastore master nodes: 127.0.0.1:19001
datastore standby nodes: none
addons:
enabled:
ha-cluster # always on — this is the Dqlite HA layer, even for a single node
disabled:
dns # ← you enable what you need, nothing runs by default beyond core
ingress
storage
...
--classic confinement is required because MicroK8s needs broader host access than a strictly-confined snap allows — it manages network interfaces, iptables/nftables rules, and mounts. This is the first place production operators coming from a bare-metal kubeadm install get surprised: MicroK8s’s snap confinement model means some host interactions happen through paths a traditional install never touches, and debugging network issues sometimes means understanding snap’s confinement boundaries, not just Kubernetes networking.
The Add-on Model: How MicroK8s Replaces a Day of Cluster Bootstrapping
Everything beyond the bare control plane is an add-on, enabled with one command:
$ microk8s enable dns storage ingress
Infer repository core for addon dns
Enabling DNS
...
DNS is enabled
Infer repository core for addon storage
Enabling default storage class
...
Storage is enabled
Infer repository core for addon ingress
Ingress controller is enabled
$ microk8s kubectl get pods -A
NAMESPACE NAME READY STATUS RESTARTS
kube-system coredns-864597b5fd-x7k2p 1/1 Running 0
kube-system hostpath-provisioner-5c65c9c74f-j9qmz 1/1 Running 0
ingress nginx-ingress-microk8s-controller-abcde 1/1 Running 0
Each add-on is a maintained, version-pinned bundle — enabling ingress doesn’t pull the latest ingress-nginx release, it pulls whatever version that MicroK8s release channel has validated. That’s the same trade seen everywhere else in this tool: predictability and speed, at the cost of being slightly behind upstream and unable to mix-and-match component versions the way a hand-built cluster can.
The cilium add-on is worth calling out specifically for platform teams already standardizing on eBPF-based networking elsewhere — it replaces MicroK8s’s default CNI with Cilium, giving you the same eBPF-enforced network policy model covered in the TC eBPF episode of the eBPF series, without a separate Cilium install process.
Dqlite Instead of etcd: MicroK8s’s Most Debated Design Choice
For high availability, upstream Kubernetes distributions almost universally reach for etcd — a mature, Raft-based key-value store with over a decade of production hardening. MicroK8s uses Dqlite instead: a distributed SQLite built by Canonical, also Raft-based, but SQL-native rather than a plain key-value store.
# Convert a single node into a 3-node HA cluster
$ microk8s add-node
From the target node, run:
microk8s join 10.0.1.15:25000/abc123... --worker
$ microk8s status
microk8s is running
high-availability: yes
datastore master nodes: 10.0.1.10:19001 10.0.1.12:19001 10.0.1.15:19001
datastore standby nodes: none
The reasoning behind Dqlite is architectural: Canonical wanted a datastore that could also serve their other projects (LXD, for instance) with a SQL interface, not just Kubernetes’ key-value needs, and one they could tightly control the release cadence of rather than depending on the etcd project’s own timeline. That’s a legitimate engineering decision — but it means MicroK8s’s HA story runs on a datastore with a small fraction of etcd’s operational track record.
Where MicroK8s Actually Runs in Production
MicroK8s’s real fit is narrower than “any Kubernetes workload”: edge and IoT deployments where a device needs a full, conformant cluster with no external dependencies (a factory sensor gateway, a retail point-of-sale cluster); CI/CD pipelines that need a disposable, fast-booting cluster per test run; and single-node developer or demo environments where Minikube’s VM overhead isn’t wanted.
It’s a weaker fit for large multi-tenant production clusters where teams already have deep etcd operational expertise, need fine-grained control-plane component versioning, or run at a scale where Dqlite’s newer, less-battle-tested Raft implementation is a harder sell to a risk-averse platform team.
⚠ Production Gotchas
Dqlite HA needs an odd number of nodes, same as etcd — but the community knowledge base is much thinner. A 2-node or 4-node Dqlite cluster has the identical split-brain risk etcd has at even node counts. The difference is that when something goes wrong, etcd has ten years of Stack Overflow answers and postmortems; Dqlite has a fraction of that.
microk8s kubectl and a separately-installed kubectl are not automatically the same context. Running both on one host is a common source of “why isn’t my change showing up” confusion — always check which kubeconfig each one is actually pointed at.
Add-on versions lag upstream by design. If a CVE fix or a new feature lands in upstream ingress-nginx or Cilium, MicroK8s’s bundled add-on version won’t have it until the next MicroK8s release validates it. Don’t assume microk8s enable X gets you the latest X.
Classic confinement means MicroK8s can conflict with other host-level network tooling. Firewalls, VPN clients, or other snap-confined networking tools on the same host can produce iptables/nftables rule conflicts that look like a Kubernetes networking bug but are actually a confinement-boundary interaction.
Quick Reference
microk8s status --wait-ready # cluster health, HA state, enabled add-ons
microk8s enable <addon> # dns, storage, ingress, metallb, cilium, gpu, ...
microk8s disable <addon> # remove an add-on
microk8s kubectl <args> # bundled kubectl, uses MicroK8s's own kubeconfig
microk8s add-node # generate a join token for HA/worker expansion
microk8s join <token> # join a node using that token
microk8s inspect # generate a full diagnostic tarball for support/debugging
microk8s remove-node <node> # remove a node from an HA cluster
Contribution Opportunity: Dqlite’s Missing Decade of Tooling
The limitation: etcd operators have etcdctl endpoint status, etcdctl endpoint health, mature snapshot/restore tooling, and a decade of documented failure-mode runbooks. Dqlite’s CLI surface for diagnosing a struggling Raft cluster — checking leader state, log index lag between nodes, or safely restoring from a snapshot after a prolonged partition — is meaningfully thinner. When a MicroK8s HA node fails to rejoin cleanly, there’s far less prior art to lean on than for the etcd equivalent.
Why it’s hard to fix: This isn’t a bug sitting in an issue tracker waiting for a quick patch. It’s a maturity gap that comes from Dqlite being a newer, narrower-scope project (built primarily to serve Canonical’s own products) maintained by a much smaller team than the decade of enterprise-scale usage that produced etcd’s tooling. Closing that gap is a sustained, multi-quarter documentation-and-tooling effort, not a single PR — and it competes for the Dqlite maintainers’ time against Canonical’s own product roadmap, which doesn’t automatically prioritize the broader Kubernetes community’s operational wishlist.
What a contribution-shaped fix looks like: Two concrete, achievable starting points that don’t require deep Raft-internals expertise: (1) a dqlite-side diagnostic command mirroring etcdctl endpoint status — human-readable leader/term/log-index output — contributed to canonical/go-dqlite; or (2) reproducing and documenting specific HA failure scenarios (node rejoin after a prolonged network partition, recovery from a minority-node failure) as runbooks in canonical/microk8s‘s own documentation repo, with the exact recovery commands verified against a real reproduction. The second option in particular is the kind of contribution an engineer who’s actually operated MicroK8s in production is uniquely positioned to make — it needs careful reproduction and clear writing, not kernel-level systems expertise.
Key Takeaways
- MicroK8s packages a full, CNCF-conformant Kubernetes cluster into a single snap install — no separate runtime, etcd, or CNI setup required
- The add-on model trades version flexibility for predictability: what you enable is validated and bundled, not necessarily the latest upstream release
- Dqlite replaces etcd for HA — a legitimate architectural choice, but one with far less operational tooling and community track record behind it
- MicroK8s’s real fit is edge/IoT, ephemeral CI clusters, and single-node dev environments — not large multi-tenant production clusters with deep etcd expertise already in place
- The clearest contribution opportunity here doesn’t require Raft internals — it requires operating MicroK8s in production long enough to hit a real failure mode and documenting it precisely
What’s Next
MicroK8s trades control for a near-instant single-command cluster. EP02 looks at Minikube — the other dominant “local Kubernetes” tool, built on a different trade-off entirely: a full VM (or container-based driver) per cluster instead of a bare-metal snap install, and where that heavier model actually earns its overhead.
Next: EP02 — Minikube: Local Kubernetes Done Right — and Where It Breaks Down
Get EP02 in your inbox when it publishes → linuxcent.com/subscribe