First Setup MicroK8s: Fixing the Defaults Before They Break You

|5 min read|

MicroK8s is one of those tools that looks dead simple until you actually try to configure it for real use. Pod CIDR conflicts, DNS that silently breaks, kubeconfig that doesn't work out of the box. Here's how I handled all of it.

Yoga Novaindra

Author

Why MicroK8s

I've run k3s, full kubeadm clusters, and even briefly touched k0s. MicroK8s sits in an interesting spot: it's opinionated enough to get running fast, but it gives you enough knobs to actually configure things the way you want. For a fresh homelab setup or a new dev cluster, it's hard to beat.

The catch is that a lot of the documentation assumes things will just work. They don't always. This is what I had to do to get it working the way I needed.


Installing MicroK8s

The install itself is straightforward. Snap handles everything:

sudo snap install microk8s --channel=latest/stable --classic

The --classic flag is required here: MicroK8s needs access outside the snap sandbox to function properly. Without it, you'll get a confusing error and no clear indication of why.

After install, add your user to the microk8s group so you're not running everything as root:

sudo usermod -a -G microk8s $USER
sudo chown -f -R $USER ~/.kube
newgrp microk8s

Changing the Default Pod CIDR

This one caught me off guard. By default, MicroK8s assigns pods from 10.1.0.0/16. That's fine unless it overlaps with your existing network, which in my case, it did. My homelab runs on 10.1.1.0/24, so pods were conflicting with real hosts on the network.

To change the pods CIDR, you actually need to configure kube-proxy and tell the Calico CNI about the new CIDR.

Here are the configuration steps I followed to switch my CIDR to 10.41.0.0/16:

First, remove the current CNI configuration:

microk8s kubectl delete -f /var/snap/microk8s/current/args/cni-network/cni.yaml

Next, edit /var/snap/microk8s/current/args/kube-proxy and update the --cluster-cidr=10.1.0.0/16 argument with the new CIDR (10.41.0.0/16).

Then, restart MicroK8s:

microk8s stop
microk8s start

Now, edit the Calico CNI manifest at /var/snap/microk8s/current/args/cni-network/cni.yaml and update the CALICO_IPV4POOL_CIDR value with the new IP range:

- name: CALICO_IPV4POOL_CIDR
  value: "10.41.0.0/16"

Finally, apply the new CNI manifest:

microk8s kubectl apply -f /var/snap/microk8s/current/args/cni-network/cni.yaml
Note: The official docs warn that changing the CIDR after nodes have already assigned addresses won't automatically migrate existing pods. If your cluster is fresh, do this first. If it's already running workloads, you'll need to drain and restart. See the official MicroK8s CIDR guide and this community thread for the full procedure.

Fixing DNS

CoreDNS is enabled as part of the dns addon, but by default it only forwards to 8.8.8.8 and 8.8.4.4. If you're running internal DNS servers (which I am, at 10.1.1.4 and 10.1.1.1), you need to tell CoreDNS to use them.

Enable the addon first if you haven't already:

microk8s enable dns

Then edit the CoreDNS ConfigMap:

microk8s kubectl -n kube-system edit configmap coredns

In the Corefile section, you'll see a forward line. Replace it with your actual DNS servers. I have two configurations depending on what I need:

# Public fallback
forward . 1.1.1.1 8.8.8.8 9.9.9.9

# Internal resolution
forward . 10.1.1.4 10.1.1.1

Pick whichever fits your setup. If you want internal-first with public fallback, you can configure it with zone-based forwarding, but that's a separate rabbit hole.

After saving the ConfigMap, the change won't take effect until you bounce the CoreDNS pods:

microk8s kubectl -n kube-system delete pod -l k8s-app=kube-dns

They'll come back automatically. Give it 30 seconds and test with a nslookup from inside a running pod to confirm.

Full docs for the DNS addon: https://microk8s.io/docs/addon-dns

Generating a Kubeconfig

If you want to use kubectl from your workstation instead of SSHing into the node every time, you need the kubeconfig. MicroK8s generates one for you:

microk8s config

That dumps the full kubeconfig to stdout. Copy it to your local machine at ~/.kube/config, or merge it in if you already have other clusters configured. Just make sure the server address in the output points to an IP your workstation can actually reach. If it says 127.0.0.1, change it to the node's real IP before copying it over.


Checking Status

Once everything is up, microk8s status gives you a clean overview of what's running:

microk8s is running
high-availability: no
  datastore master nodes: 10.1.1.11:19001
  datastore standby nodes: none
addons:
  enabled:
    dns                  # (core) CoreDNS
    ha-cluster           # (core) Configure high availability on the current node
    helm                 # (core) Helm - the package manager for Kubernetes
    helm3                # (core) Helm 3 - the package manager for Kubernetes
    metrics-server       # (core) K8s Metrics Server for API access to service metrics

This is what a healthy initial setup looks like. The ha-cluster addon shows up even before you add any additional nodes; it's part of the datastore configuration. The datastore standby nodes: none just means you haven't clustered yet, which is completely expected for a first run.


A Few Things That Tripped Me Up

Snap refresh breaking things. Snap can update MicroK8s automatically in the background. If something stops working after a few days and you haven't changed anything, check snap changes to see if a refresh ran. You can hold the version with sudo snap refresh --hold microk8s if you'd rather control when updates happen.

Permissions on the kubeconfig. If you're hitting permission denied errors when using kubectl, make sure you've actually added your user to the microk8s group and started a fresh shell session. The newgrp microk8s command handles this without a full logout.

CoreDNS not picking up ConfigMap changes. Editing the ConfigMap and expecting it to hot-reload doesn't always work reliably. When in doubt, just delete the pods. Kubernetes will recreate them immediately and they'll pick up the new config fresh on start.


MicroK8s gets you to a working cluster fast, but the defaults aren't always a fit for every environment. Once you sort out the CIDR and DNS pieces, it's actually a solid platform. The snap-based packaging makes upgrades simple, the addon system keeps things modular, and it doesn't need nearly as much babysitting as a full kubeadm cluster.

For your first homelab Kubernetes cluster or a quick dev environment, it's my current go-to.

© 2026 Yoga Novaindra Powered by Ghost