MicroK8s Installation and Diagnostics
Objective
MicroK8s is Canonical's single-package Kubernetes: one snap that contains the API server, scheduler, controller manager, kubelet, kube-proxy, containerd, a CNI (Calico) and a datastore. It is a common choice for a single-node production box, an edge site or a lab machine, because it installs in one command and upgrades through snap channels. This concept covers installing it with a pinned version channel, checking that the cluster is actually ready, running kubectl without sudo, and collecting a diagnostic report when something is wrong.
Use Cases
- Standing up a one-node Kubernetes on an Ubuntu VM or bare-metal server for a small production setup.
- Pinning the cluster to a Kubernetes minor version so an automatic snap refresh never jumps you to the next one.
- Scripting a bootstrap that waits for the cluster before applying manifests.
- Attaching a support bundle (
microk8s inspect) to an issue or handing it to a colleague.
Deep Dive
Installing with a version channel
plaintextsudo snap install microk8s --classic --channel=1.35/stable
--classicis required: MicroK8s needs access to the host (network, mounts, cgroups) that a strictly confined snap does not get.- The channel is
<k8s-minor>/<risk>.1.35/stablemeans "the latest stable 1.35.x". Snap refreshes automatically, but only inside the tracked channel: you get 1.35.5 to 1.35.6 patch updates, never 1.36. - Without
--channelyou tracklatest/stable, which moves to a new minor version when Canonical promotes it. For anything you care about, always pin.
Moving to the next minor is an explicit action:
plaintextsudo snap refresh microk8s --channel=1.36/stable
Check what you are tracking and what exists:
plaintextsnap list microk8s # installed version, revision, tracking channel snap info microk8s # all channels and their versions
Verified on a fresh Ubuntu 24.04 VM (September 2026): 1.35/stable installed v1.35.6, tracking 1.35/stable. At that date 1.36 was released upstream by MicroK8s but still being promoted through the channels, which is exactly why you pin.
Snap refreshes also restart the MicroK8s services. Verified with snap restart microk8s: running containers kept running (restart count 0), but the API server is unavailable for a while, so deploys and scheduling pause until it is back. You can control the window:
plaintextsudo snap set system refresh.timer=sat,03:00-04:00 # refresh window sudo snap refresh --hold=720h microk8s # postpone refreshes of this snap
What runs inside the snap
MicroK8s does not run the control plane as separate Pods like kubeadm does. The Kubernetes components run in one process, kubelite, managed by systemd:
plaintextsnap.microk8s.daemon-containerd snap.microk8s.daemon-kubelite # apiserver + scheduler + controller-manager + kubelet + proxy snap.microk8s.daemon-k8s-dqlite # the datastore (dqlite, not etcd) snap.microk8s.daemon-apiserver-kicker snap.microk8s.daemon-cluster-agent
Two consequences: kubectl get pods -n kube-system shows only add-ons (Calico, CoreDNS, ...), never a kube-apiserver Pod; and the datastore is dqlite, so etcd-specific tooling (etcdctl snapshot) does not apply.
Is it ready?
plaintextmicrok8s status --wait-ready
--wait-ready blocks until the API server answers, which makes it the right first line of any bootstrap script. The output also lists which add-ons are enabled. On a fresh 1.35 install, dns is already enabled; hostpath-storage, ingress, rbac and metrics-server are not.
Then check the node itself:
plaintextmicrok8s kubectl get nodes -o wide microk8s kubectl get pods -A
A Ready node with calico-node, calico-kube-controllers and coredns running is a working cluster.
Running kubectl without sudo
Out of the box, every command needs sudo. Running microk8s status as a normal user prints the fix:
plaintextInsufficient permissions to access MicroK8s. You can either try again with sudo or add the user ubuntu to the 'microk8s' group: sudo usermod -a -G microk8s ubuntu sudo chown -R ubuntu ~/.kube
plaintextsudo usermod -a -G microk8s $USER mkdir -p ~/.kube && sudo chown -R $USER ~/.kube newgrp microk8s # or log out and back in
Membership of the microk8s group is effectively cluster-admin: the group can read the admin credentials under /var/snap/microk8s/current/credentials. Treat it like the docker group.
microk8s kubectl is a bundled kubectl matching the cluster version. Two ways to type less:
plaintextsudo snap alias microk8s.kubectl kubectl # system-wide alias alias kubectl='microk8s kubectl' # shell alias only
The snap alias conflicts with a separately installed kubectl. If you use a standalone kubectl (to talk to several clusters), export the kubeconfig instead, see the kubeconfig concept.
Collecting diagnostics
plaintextsudo microk8s inspect
It checks every service (Service snap.microk8s.daemon-kubelite is running), copies the args of each component, the process list, disk and memory usage, network configuration, inotify limits and a dqlite dump into a tarball:
plaintextBuilding the report tarball Report tarball is at /var/snap/microk8s/<revision>/inspection-report-<date>.tar.gz
It also prints warnings for common host problems, such as the firewall blocking Pod traffic or IP forwarding being disabled. For a single failing service, the systemd journal is faster:
plaintextsudo journalctl -u snap.microk8s.daemon-kubelite --since "10 min ago"
Trade-offs
- Automatic patch refreshes vs control. Staying inside a channel gives you security patches for free, at the price of an unplanned restart. On a single-node production box, set a refresh window or hold refreshes and patch deliberately.
- Bundled
microk8s kubectlvs standalone kubectl. The bundled one always matches the server version and needs no config. A standalone kubectl is needed as soon as you manage more than one cluster or run commands from your laptop or CI. - The
microk8sgroup is convenient and powerful. Adding a user to it is granting full cluster access, not "permission to run kubectl". - Single package, single failure domain. One
kubeliteprocess restart restarts the whole control plane and the kubelet. That is fine for one node; for real availability you need three nodes (microk8s add-node) and theha-clusteradd-on.