This guide provides essential commands for debugging and troubleshooting MicroK8s Kubernetes clusters. These commands help diagnose networking issues, inspect cluster state, analyze pod failures, and monitor resource usage.
Cluster Configuration
Get Kubernetes API
Ensure the Pod CIDR is consistent across the cluster. Check the API server flags
1cat /var/snap/microk8s/current/args/kube-apiserverThe kube-apiserver is the central management entity that validates and configures API objects such as pods, services, and replication controllers. Key flags to look for include:
--service-cluster-ip-range: Defines the IP range for cluster services--secure-port: The port on which to serve HTTPS (default: 6443)--authorization-mode: Authorization modes (e.g., RBAC, Node)--enable-admission-plugins: Enabled admission control plugins
You can also check other control plane component configurations:
1# Check kubelet configuration2cat /var/snap/microk8s/current/args/kubelet3
4# Check controller-manager settings5cat /var/snap/microk8s/current/args/kube-controller-manager6
7# Check scheduler configuration8cat /var/snap/microk8s/current/args/kube-schedulerDNS and Networking
Check the CoreDNS configuration
CoreDNS is the default DNS server in Kubernetes that provides DNS-based service discovery. It reads its configuration from a ConfigMap and supports various plugins for DNS resolution, caching, and forwarding.
1microk8s kubectl describe configmap -n kube-system corednsKey CoreDNS plugins to understand:
| Plugin | Purpose |
|---|---|
errors | Logs errors to stdout for debugging |
ready | Provides health check endpoint on port 8181 |
kubernetes | Handles DNS queries for cluster services and pods |
forward | Forwards external DNS queries to upstream resolvers |
cache | Enables DNS response caching (default: 30s) |
loop | Detects and prevents DNS forwarding loops |
reload | Auto-reloads configuration changes (takes ~2 minutes) |
loadbalance | Round-robin load balancing for A/AAAA/MX records |
To view CoreDNS logs for debugging DNS resolution issues:
1microk8s kubectl logs -n kube-system -l k8s-app=kube-dns --tail=100Check if the CNI is working
The Container Network Interface (CNI) plugin manages pod networking. MicroK8s uses Calico as the default CNI. A healthy cluster should show all kube-system pods in Running state.
1microk8s kubectl get pods -n kube-systemUnderstanding CNI states:
- Pending: Usually indicates the CNI isn't installed yet (CoreDNS will remain Pending without a network plugin)
- Running: Pod is healthy and operational
- CrashLoopBackOff: Pod is repeatedly crashing - check logs for details
- ContainerCreating: Pod is being created, CNI is allocating network resources
You can verify CNI plugin status and network policy:
1# Check Calico node status (if using Calico CNI)2microk8s kubectl get pods -n kube-system -l k8s-app=calico-node3
4# View network policies5microk8s kubectl get networkpolicies -A6
7# Check pod network connectivity8microk8s kubectl run test-pod --image=busybox --rm -it --restart=Never -- wget -qO- http://kubernetes.default.svc.cluster.local/healthzDebugging Pods
Debug CrashLoopBackOff Pods
The CrashLoopBackOff status indicates a pod is repeatedly failing to start. Common causes include:
- Application errors: Crashes due to bugs or missing configuration
- Resource limits: Out of memory (OOMKilled) or CPU throttling
- Probe failures: Liveness or readiness probes failing
- Missing dependencies: ConfigMaps, Secrets, or volumes not found
- Image issues: Wrong image tag or pull failures
1microk8s kubectl describe pod -n kube-system coredns-7896dbf49-87b67Key sections to examine in describe output:
- Events: Shows recent scheduling and container events
- State/Last State: Current and previous container state with exit codes
- Restart Count: Number of times the container has restarted
- Conditions: Ready, Initialized, ContainersReady, PodScheduled
Additional debugging commands:
1# View pod logs (current instance)2microk8s kubectl logs -n kube-system coredns-7896dbf49-87b673
4# View logs from previous crashed container5microk8s kubectl logs -n kube-system coredns-7896dbf49-87b67 --previous6
7# Follow logs in real-time8microk8s kubectl logs -n kube-system coredns-7896dbf49-87b67 -f9
10# Get logs from specific container in multi-container pod11microk8s kubectl logs -n kube-system <pod-name> -c <container-name>Interactive Pod Debugging
Use kubectl debug to create ephemeral debugging containers or copies of failing pods:
1# Create an interactive debugging session in a running pod2microk8s kubectl debug mypod -it --image=busybox3
4# Create a copy of a pod with a debug container attached5microk8s kubectl debug mypod -it --image=busybox --copy-to=my-debugger6
7# Debug a node directly (container runs in host namespaces)8microk8s kubectl debug node/mynode -it --image=busyboxCommon Exit Codes Reference
| Exit Code | Meaning |
|---|---|
| 0 | Success (container completed normally) |
| 1 | Application error |
| 137 | Container killed (OOMKilled or SIGKILL) |
| 139 | Segmentation fault (SIGSEGV) |
| 143 | Graceful termination (SIGTERM) |
Certificate Management
Refresh Certificates
Kubernetes uses TLS certificates for secure communication between components. MicroK8s provides a convenient command to refresh certificates when they expire or need rotation.
1sudo microk8s refresh-certs --cert server.crtAvailable certificate options: 'server.crt': refreshes the server certificate 'front-proxy-client.crt': refreshes the front proxy client certificate 'ca.crt': refreshes the root CA and all certificates created from it. Warning: refreshing the root CA requires nodes to leave and re-join the cluster
Certificate expiration check:
1# Check certificate expiration dates2sudo microk8s kubectl get csr3
4# View certificate details5openssl x509 -in /var/snap/microk8s/current/certs/server.crt -text -noout | grep -A2 "Validity"Understanding Kubernetes certificates:
| Certificate | Purpose |
|---|---|
server.crt | API server serving certificate |
front-proxy-client.crt | Client cert for front-proxy (aggregation layer) |
ca.crt | Root Certificate Authority for the cluster |
kubelet.crt | Kubelet serving certificate |
etcd/server.crt | etcd server certificate |
Cluster Inspection and Configuration
Inspect cluster
The inspect command collects detailed diagnostic information about your MicroK8s cluster and saves it to a tarball for analysis or sharing with support teams.
1microk8s inspectThis command gathers:
- Service status for all MicroK8s daemons
- Network configuration and iptables rules
- Kubernetes API server, controller-manager, and scheduler logs
- kubelet and containerd logs
- CNI configuration and status
- Storage and addon configurations
Print config
Export the kubeconfig file for use with external kubectl clients or for backup purposes.
1sudo microk8s kubectl config view --rawTo save the kubeconfig to a file for external access:
1# Export kubeconfig to file2sudo microk8s kubectl config view --raw > ~/.kube/microk8s-config3
4# Use with standard kubectl5export KUBECONFIG=~/.kube/microk8s-config6kubectl get nodesCheck logs cluster agent
The cluster-agent daemon handles multi-node cluster operations including node joining, token management, and cluster state synchronization.
1journalctl -u snap.microk8s.daemon-cluster-agentView logs for other MicroK8s daemons:
1# API server logs2journalctl -u snap.microk8s.daemon-apiserver3
4# Kubelet logs5journalctl -u snap.microk8s.daemon-kubelet6
7# Containerd logs8journalctl -u snap.microk8s.daemon-containerd9
10# Follow logs in real-time11journalctl -u snap.microk8s.daemon-kubelet -fGet all Pods info
List all pods across all namespaces with detailed information including node placement and IP addresses.
1microk8s kubectl get pods -A -o wideOutput columns explained:
| Column | Description |
|---|---|
| NAMESPACE | The namespace where the pod runs |
| NAME | Pod name (includes ReplicaSet hash for deployments) |
| READY | Containers ready vs total (e.g., 1/1) |
| STATUS | Current pod phase (Running, Pending, etc.) |
| RESTARTS | Number of container restarts |
| AGE | Time since pod creation |
| IP | Pod's internal cluster IP |
| NODE | Node where the pod is scheduled |
Additional useful listing commands:
1# Get pods with labels2microk8s kubectl get pods -A --show-labels3
4# Get pods sorted by restart count5microk8s kubectl get pods -A --sort-by='.status.containerStatuses[0].restartCount'6
7# Get pods in JSON format for parsing8microk8s kubectl get pods -A -o json | jq '.items[] | {name: .metadata.name, status: .status.phase}'9
10# Watch pods in real-time11microk8s kubectl get pods -A -wCluster Events
Events provide a timeline of what's happening in your cluster. They're crucial for debugging scheduling, networking, and container issues.
1# Get all events sorted by timestamp2microk8s kubectl get events -A --sort-by='.lastTimestamp'3
4# Get events for a specific namespace5microk8s kubectl get events -n kube-system6
7# Watch events in real-time8microk8s kubectl get events -A -w9
10# Get warning events only11microk8s kubectl get events -A --field-selector type=WarningMonitoring
The Metrics Server is a cluster-wide aggregator of resource usage data. It collects metrics from the kubelet's Summary API and exposes them through the Kubernetes Metrics API, which is used by kubectl top and Horizontal Pod Autoscaler (HPA).
Enabling the Metrics Server in MicroK8s
1microk8s enable metrics-serverAfter enabling, wait 1-2 minutes for the metrics-server pod to become ready and start collecting data.
1# Verify metrics-server is running2microk8s kubectl get pods -n kube-system -l k8s-app=metrics-server3
4# Check if metrics API is available5microk8s kubectl get --raw "/apis/metrics.k8s.io/v1beta1/nodes" | jq '.'Check nodes usage
View CPU and memory consumption across all nodes in the cluster.
1microk8s kubectl top nodesUnderstanding the output:
| Metric | Description |
|---|---|
| CPU(cores) | Current CPU usage in millicores (m) or cores |
| CPU% | Percentage of allocatable CPU being used |
| MEMORY(bytes) | Current memory usage in bytes (Mi/Gi) |
| MEMORY% | Percentage of allocatable memory being used |
Check pods usage
Monitor resource consumption of all pods across namespaces.
1microk8s kubectl top pods -AAdditional monitoring commands:
1# Get resource usage for pods in a specific namespace2microk8s kubectl top pods -n kube-system3
4# Sort pods by CPU usage5microk8s kubectl top pods -A --sort-by=cpu6
7# Sort pods by memory usage8microk8s kubectl top pods -A --sort-by=memory9
10# Get container-level resource usage11microk8s kubectl top pods -A --containersRaw Metrics API Access
Access the Metrics API directly for advanced monitoring or automation:
1# Get metrics for a specific node2microk8s kubectl get --raw "/apis/metrics.k8s.io/v1beta1/nodes/<node-name>" | jq '.'3
4# Get metrics for a specific pod5microk8s kubectl get --raw "/apis/metrics.k8s.io/v1beta1/namespaces/<namespace>/pods/<pod-name>" | jq '.'Example response structure:
1{2 "kind": "NodeMetrics",3 "apiVersion": "metrics.k8s.io/v1beta1",4 "metadata": { "name": "mynode" },5 "timestamp": "2026-01-21T10:30:00Z",6 "window": "30s",7 "usage": {8 "cpu": "487558164n",9 "memory": "732212Ki"10 }11}CPU units explained:
n(nanocores): 1 core = 1,000,000,000nm(millicores): 1 core = 1000m1= 1 full CPU core
Memory units explained:
Ki(kibibytes): 1024 bytesMi(mebibytes): 1024 KiGi(gibibytes): 1024 Mi
Resource Quotas and Limits
To prevent resource exhaustion, define ResourceQuotas for namespaces:
1apiVersion: v12kind: ResourceQuota3metadata:4 name: compute-quota5 namespace: development6spec:7 hard:8 requests.cpu: "4"9 requests.memory: 8Gi10 limits.cpu: "8"11 limits.memory: 16Gi12 pods: "20"Apply and verify:
1# Apply the quota2microk8s kubectl apply -f quota.yaml3
4# Check quota usage5microk8s kubectl describe resourcequota -n developmentUseful Aliases
Add these aliases to your ~/.bashrc or ~/.zshrc for faster troubleshooting:
1alias mk='microk8s kubectl'2alias mkgp='microk8s kubectl get pods -A'3alias mkgs='microk8s kubectl get svc -A'4alias mkgn='microk8s kubectl get nodes -o wide'5alias mklog='microk8s kubectl logs -f'6alias mktop='microk8s kubectl top pods -A --sort-by=memory'7alias mkevents='microk8s kubectl get events -A --sort-by=.lastTimestamp'