MicroK8s Installation and Configuration

MicroK8s is a snap package providing a single-command Kubernetes installation optimized for developers, IoT, and edge deployments. This guide covers snap installation, enabling addons, clustering multiple nodes, storage and DNS configuration, dashboard access, and local registry setup for your VPS and baremetal infrastructure.

Table of Contents

MicroK8s Overview

What is MicroK8s?

MicroK8s is a production-grade Kubernetes distribution that:

  • Installs as single snap package
  • Minimal system requirements (20MB footprint)
  • Batteries-included with common addons
  • Perfect for development and testing
  • Fully compatible with upstream Kubernetes

MicroK8s vs K3s

AspectMicroK8sK3s
InstallationSnap packageBinary download
ComponentsModular addonsMinimal included
ClusteringEasy multi-nodeMulti-node possible
UpdatesAutomatic snap updatesManual
DashboardAvailable addonRequires install
Learning CurveEasyVery easy

System Requirements

  • Ubuntu 20.04+ or Linux with snapd
  • 4GB+ RAM recommended
  • 20GB+ disk space
  • Internet connectivity for addon downloads

Installation via Snap

Installing MicroK8s

On Ubuntu/Debian with snapd:

# Install MicroK8s
sudo snap install microk8s --classic

# Add user to microk8s group
sudo usermod -a -G microk8s $USER
sudo chown -f -R $USER ~/.kube

# Apply group changes
newgrp microk8s

# Verify installation
microk8s status
microk8s kubectl version

Starting and Stopping

# Start MicroK8s
microk8s start

# Stop MicroK8s
microk8s stop

# Check status
microk8s status

# View service status
sudo systemctl status snap.microk8s.daemon-kubelet

Updating MicroK8s

# Refresh to latest version
sudo snap refresh microk8s

# Install specific version
sudo snap install microk8s --classic --channel=1.28/stable

# Hold current version
sudo snap hold microk8s
sudo snap unhold microk8s

Accessing kubectl

# Via microk8s
microk8s kubectl get nodes

# Alternatively, install standalone kubectl
sudo snap install kubectl --classic

# Configure kubeconfig
microk8s config > ~/.kube/config
chmod 600 ~/.kube/config

# Verify
kubectl get nodes

Addons

Viewing Available Addons

# List all addons
microk8s addons

# Example output:
# core/dns                       # DNS service
# core/dashboard                 # Kubernetes dashboard
# core/storage                   # Storage provisioner

Common Addons

DNS (core DNS):

microk8s enable dns
microk8s disable dns

Dashboard (web UI):

microk8s enable dashboard

Access dashboard:

# Get token
token=$(microk8s kubectl -n kube-system get secret \
  $(microk8s kubectl -n kube-system get secret | grep default-token | cut -d " " -f1) \
  -o jsonpath='{.data.token}' | base64 --decode)

# Port forward
microk8s kubectl port-forward -n kube-system svc/kubernetes-dashboard 10443:443

# Access: https://localhost:10443

Storage (local-path storage):

microk8s enable storage

Verify:

microk8s kubectl get storageclass

Registry (local container registry):

microk8s enable registry

Use local registry:

# Push image to local registry
docker tag myapp:1.0 localhost:32000/myapp:1.0
docker push localhost:32000/myapp:1.0

# Use in pod
microk8s kubectl apply -f - << 'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: test
spec:
  containers:
  - name: app
    image: localhost:32000/myapp:1.0
EOF

Metrics Server (resource metrics):

microk8s enable metrics-server

Prometheus (monitoring):

microk8s enable prometheus

Enabling/Disabling Addons

# Enable addon
microk8s enable addon-name

# Disable addon
microk8s disable addon-name

# Enable multiple addons
microk8s enable dns storage dashboard

Clustering

Creating Multi-Node Cluster

On first node (primary):

# Get join command
microk8s add-node

# Output:
# From the node you wish to join to this cluster, run:
#
# microk8s join 192.168.1.100:25000/abcdef...

On worker nodes:

# Install MicroK8s
sudo snap install microk8s --classic

# Join cluster
microk8s join 192.168.1.100:25000/abcdef...

# Verify join from primary
microk8s kubectl get nodes

Verifying Cluster

# View all nodes
microk8s kubectl get nodes

# View node details
microk8s kubectl describe node node-name

# Check cluster info
microk8s kubectl cluster-info

Removing Node from Cluster

On primary node:

# Remove worker node
microk8s remove-node node-name

# Verify
microk8s kubectl get nodes

Storage Configuration

Using Storage Addon

Enable storage:

microk8s enable storage

Create persistent volume:

microk8s kubectl apply -f - << 'EOF'
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-data
spec:
  accessModes:
  - ReadWriteOnce
  storageClassName: microk8s-hostpath
  resources:
    requests:
      storage: 10Gi
EOF

Use in pod:

microk8s kubectl apply -f - << 'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: storage-test
spec:
  containers:
  - name: app
    image: busybox
    volumeMounts:
    - name: data
      mountPath: /data
  volumes:
  - name: data
    persistentVolumeClaim:
      claimName: my-data
EOF

Custom Storage Location

By default, storage uses /var/snap/microk8s/common/default-storage/. To change:

# Stop MicroK8s
microk8s stop

# Change storage directory
sudo mkdir -p /mnt/storage
sudo chown root:root /mnt/storage
sudo chmod 755 /mnt/storage

# Edit storage addon configuration
sudo vi /var/snap/microk8s/current/args/storage-addon

# Start MicroK8s
microk8s start

DNS Setup

DNS Addon

Enable DNS:

microk8s enable dns

Testing DNS

# Check DNS pods
microk8s kubectl get pods -n kube-system | grep dns

# Test DNS resolution
microk8s kubectl run -it --rm debug --image=busybox -- sh
# Inside pod:
# nslookup kubernetes.default
# dig service-name.namespace.svc.cluster.local

Custom DNS Records

Edit CoreDNS ConfigMap:

microk8s kubectl edit configmap -n kube-system coredns

Add custom records in hosts section:

hosts {
  10.0.0.1 custom.local
  fallthrough
}

Dashboard and Monitoring

Dashboard

Enable dashboard:

microk8s enable dashboard

Access:

# Get token
microk8s kubectl -n kube-system describe secret \
  $(microk8s kubectl -n kube-system get secret | grep default-token | cut -d " " -f1)

# Port forward
microk8s kubectl port-forward -n kube-system svc/kubernetes-dashboard 10443:443

# Open: https://localhost:10443

Prometheus

Enable monitoring:

microk8s enable prometheus

Access Prometheus:

microk8s kubectl port-forward -n monitoring svc/prometheus 9090:9090
# Visit: http://localhost:9090

Grafana

Install Grafana:

microk8s kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/main/example/prometheus-operator-crd.yaml

# Or deploy manually
microk8s kubectl apply -f - << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: grafana
  namespace: monitoring
spec:
  replicas: 1
  selector:
    matchLabels:
      app: grafana
  template:
    metadata:
      labels:
        app: grafana
    spec:
      containers:
      - name: grafana
        image: grafana/grafana:9.5.0
        ports:
        - containerPort: 3000
EOF

Access:

microk8s kubectl port-forward -n monitoring svc/grafana 3000:3000
# Visit: http://localhost:3000

Practical Examples

Example: Single-Node Development Cluster

#!/bin/bash

echo "=== Installing MicroK8s ==="
sudo snap install microk8s --classic
sudo usermod -a -G microk8s $USER
newgrp microk8s

echo "=== Starting MicroK8s ==="
microk8s start
sleep 10

echo "=== Enabling Core Addons ==="
microk8s enable dns storage dashboard

echo "=== Configuring kubectl ==="
microk8s config > ~/.kube/config

echo "=== Verifying Installation ==="
microk8s kubectl cluster-info
microk8s kubectl get nodes
microk8s kubectl get pods -A

echo "=== Setup Complete ==="
echo "Access dashboard: microk8s kubectl port-forward -n kube-system svc/kubernetes-dashboard 10443:443"

Example: Multi-Node Production Cluster

#!/bin/bash

PRIMARY_NODE="192.168.1.100"
WORKER_NODES=("192.168.1.101" "192.168.1.102")

echo "=== Setting up Primary Node ==="
ssh root@$PRIMARY_NODE << 'EOF'
sudo snap install microk8s --classic
sudo usermod -a -G microk8s ubuntu
microk8s enable dns storage
EOF

# Get join token
JOIN_CMD=$(ssh root@$PRIMARY_NODE "microk8s add-node | grep 'microk8s join'")

echo "=== Joining Worker Nodes ==="
for node in "${WORKER_NODES[@]}"; do
  echo "Joining $node..."
  ssh root@$node << EOF
sudo snap install microk8s --classic
sudo usermod -a -G microk8s ubuntu
$JOIN_CMD
EOF
done

echo "=== Verifying Cluster ==="
ssh root@$PRIMARY_NODE "microk8s kubectl get nodes"

Example: Local Registry Setup

#!/bin/bash

echo "=== Enabling Local Registry ==="
microk8s enable registry

echo "=== Building and Pushing Image ==="

# Build app
docker build -t myapp:1.0 .

# Tag for local registry
docker tag myapp:1.0 localhost:32000/myapp:1.0

# Push to registry
docker push localhost:32000/myapp:1.0

echo "=== Deploying from Local Registry ==="
microk8s kubectl apply -f - << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: app
        image: localhost:32000/myapp:1.0
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
EOF

Conclusion

MicroK8s provides an excellent entry point to Kubernetes for developers and small deployments. Its snap-based installation, modular addons, and straightforward clustering make it ideal for learning Kubernetes and running small production workloads on VPS and baremetal servers. Start with a single-node installation for development, leverage addons for required functionality, and scale to multi-node clusters as needed. MicroK8s demonstrates that Kubernetes doesn't require complex infrastructure, making it perfect for teams starting their Kubernetes journey.