Kubernetes Ecosystem: From User to Contributor, Episode 2
← EP01: MicroK8s Explained · EP02: Minikube · EP03: k3s vs MicroK8s vs Minikube →
11 min read
TL;DR
- What is Minikube? A tool that runs a single-node Kubernetes cluster inside a VM or a container on your local machine — the oldest and most widely adopted “local Kubernetes” tool in the ecosystem
- Unlike MicroK8s’s bare-metal snap install, Minikube’s default drivers isolate the cluster inside a VM (VirtualBox, HyperKit, Hyper-V, KVM2) or a Docker container — a deliberate isolation trade-off, not an accident
minikube addons,minikube profile, and multi-node support let you run several named clusters side by side, each with its own driver and Kubernetes versionLoadBalancerservices don’t resolve to anything real on their own —minikube tunnelorminikube serviceare required, and this trips up almost everyone the first time- The VM overhead that makes Minikube heavier than MicroK8s is also what makes it a more faithful stand-in for a real cloud node, particularly for testing kernel-adjacent behavior
- Contribution opportunity: feature parity across Minikube’s own driver list is uneven, and closing specific gaps there is a well-scoped, achievable contribution
The Big Picture
MICROK8S: BARE-METAL SNAP MINIKUBE: ISOLATED VM/CONTAINER
────────────────────────── ──────────────────────────────
Host OS
└── microk8s snap Host OS
├── kubelet └── Driver (VirtualBox / KVM2 /
├── kube-apiserver HyperKit / Docker / Podman)
├── containerd └── VM or container
└── Dqlite ├── kubelet
├── kube-apiserver
No VM boundary — cluster ├── etcd
runs directly on the host └── containerd
kernel and network stack
Full isolation boundary between
cluster and host — closer to how
a real cloud node actually looks
What is Minikube? It’s the tool that popularized “just run a Kubernetes cluster on your laptop” — a single command that provisions a VM or container, installs a full Kubernetes control plane and node inside it, and hands you a working kubectl context. The isolation boundary that VM makes MicroK8s’s bare-metal install avoid is the entire point: Minikube trades startup speed and resource overhead for a cluster that behaves more like a real, separate node — the same control-plane/node split covered in detail in this site’s Kubernetes history series, just shrunk down to fit on a laptop.
The Driver Model: How Minikube Actually Runs Your Cluster
Minikube doesn’t run Kubernetes directly on your host. It provisions a driver-specific environment first, then runs Kubernetes inside that:
$ minikube start --driver=docker
😄 minikube v1.32.0 on Darwin 14.2
✨ Using the docker driver based on user configuration
👍 Starting control plane node minikube in cluster minikube
🚜 Pulling base image ...
🔥 Creating docker container (CPUs=2, Memory=4000MB) ...
🐳 Preparing Kubernetes v1.28.3 on Docker 24.0.7 ...
🔎 Verifying Kubernetes components...
🌟 Enabled addons: default-storageclass, storage-provisioner
🏄 Done! kubectl is now configured to use "minikube" cluster
$ minikube status
minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured
The --driver flag is the real decision point. docker/podman drivers run the cluster as a container, which is fast to start but shares the host kernel — you don’t get true kernel-level isolation. virtualbox/hyperkit/kvm2/hyperv drivers run a full VM, which is slower to start (30–90 seconds, versus 10–20 for the container driver) but gives the cluster its own kernel, its own network namespace, and behavior much closer to an actual cloud instance.
Addons and Profiles: Minikube’s Answer to Multi-Environment Testing
$ minikube addons list
|-----------------------------|----------|--------------|
| ADDON NAME | PROFILE | STATUS |
|-----------------------------|----------|--------------|
| ingress | minikube | disabled |
| metrics-server | minikube | disabled |
| dashboard | minikube | disabled |
| registry | minikube | disabled |
$ minikube addons enable ingress
🔎 Verifying ingress addon...
🌟 The 'ingress' addon is enabled
# Run a second, independent cluster on a different Kubernetes version
$ minikube start -p old-version --kubernetes-version=v1.26.0
$ minikube profile list
|----------|-----------|---------|--------------|------|
| Profile | VM Driver | Runtime | IP | Ver |
|----------|-----------|---------|--------------|------|
| minikube | docker | docker | 192.168.49.2 | v1.28.3 |
| old-version | docker | docker | 192.168.58.2 | v1.26.0 |
Profiles are Minikube’s way of running multiple, fully independent clusters side by side — useful for testing an upgrade path or comparing behavior across Kubernetes versions without tearing anything down. MicroK8s has no equivalent to this; it’s a genuine Minikube differentiator, not just a different flavor of the same feature.
Where the VM Overhead Actually Shows Up
The isolation Minikube provides isn’t free, and it shows up in three concrete places: startup time (a VM driver cold-start is measured in tens of seconds, not the few seconds a bare-metal snap install takes), memory floor (a VM needs to reserve memory for its own kernel and init system before Kubernetes gets any of it), and CI runners specifically — many hosted CI environments (GitHub Actions’ standard runners, for example) don’t support nested virtualization, which rules out VM drivers entirely and forces the docker driver, quietly giving up the isolation benefit that was the reason to pick Minikube over MicroK8s in the first place.
Networking Quirks: LoadBalancer Services and minikube tunnel
This is the single most common point of confusion for anyone coming from a real cloud cluster:
$ kubectl expose deployment web --type=LoadBalancer --port=80
service/web exposed
$ kubectl get svc web
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
web LoadBalancer 10.96.34.201 <pending> 80:31234/TCP
# ^^^^^^^^^ stays pending forever —
# there's no cloud load balancer to provision one
Minikube has no cloud provider to actually satisfy a LoadBalancer request. Two ways to actually reach the service:
# Option 1: minikube tunnel — creates a real route to LoadBalancer services,
# must stay running in a foreground terminal the whole time
$ minikube tunnel
✅ Tunnel successfully started
# Option 2: minikube service — opens the service in a browser via NodePort,
# no LoadBalancer semantics, but doesn't require a background process
$ minikube service web --url
http://192.168.49.2:31234
minikube tunnel is the closer match to real LoadBalancer behavior, but it’s a foreground process that silently stops working if the terminal closes or the machine sleeps — a frequent source of “it worked five minutes ago” confusion.
⚠ Production Gotchas
Nested virtualization isn’t available everywhere. Many hosted CI runners and some cloud dev environments don’t expose the CPU virtualization extensions Minikube’s VM drivers need — you’ll get a driver failure that looks like a Minikube bug but is actually a host capability gap. Falling back to --driver=docker works, but changes the isolation guarantees you were relying on.
The docker driver shares your host’s Docker daemon resource limits. If your host Docker Desktop is capped at 4GB, that’s a hard ceiling for everything running inside the Minikube container too — VM drivers get their own explicit memory allocation instead.
minikube tunnel dying silently is the most common “why can’t I reach my LoadBalancer” support question. It doesn’t reliably surface a clear error when it stops — check minikube tunnel‘s own terminal output before assuming the Kubernetes side is broken.
Addon behavior differs meaningfully by driver. The ingress addon’s interaction with host networking is different between a VM driver (which gets its own IP on a virtual network) and the docker driver (which shares the host’s Docker network) — a setup that works on one driver doesn’t automatically work identically on another.
Quick Reference
minikube start --driver=<docker|virtualbox|hyperkit|kvm2|hyperv>
minikube status # cluster health
minikube addons list # available and enabled add-ons
minikube addons enable <name> # enable one
minikube profile list # all named clusters
minikube start -p <name> # start/create a named profile
minikube tunnel # real LoadBalancer routing (foreground)
minikube service <name> --url # NodePort-based access, no LB semantics
minikube delete -p <name> # tear down a specific profile
minikube ssh # shell into the cluster's VM/container
Contribution Opportunity: Closing Minikube’s Driver Feature-Parity Gaps
The limitation: Minikube supports over a dozen drivers (docker, podman, virtualbox, hyperkit, kvm2, hyperv, vfkit, qemu, and more), and features don’t land on all of them at the same time or with the same fidelity. GPU passthrough, specific CNI plugin support, and certain addon behaviors work reliably on some drivers and only partially — or not at all — on others. A user picking a driver based on their OS often has no easy way to know upfront which features they’re implicitly giving up.
Why it’s hard to fix: Each driver wraps a fundamentally different underlying technology (a type-2 hypervisor, a container runtime, a different hypervisor API per OS), so a feature that’s straightforward on one driver can require an entirely separate implementation path on another — this isn’t a matter of one team finishing a checklist, it’s N different integration surfaces that each need their own maintainer attention, and Minikube’s driver maintainers are a much smaller, more fragmented group than the core Kubernetes maintainers.
What a contribution-shaped fix looks like: The achievable starting point isn’t “add GPU support to every driver” — it’s picking one specific, well-documented gap (say, a particular addon’s known behavior difference on hyperv versus kvm2), reproducing it precisely, and either fixing the driver-specific code path in kubernetes/minikube or, just as valuably, contributing a clear compatibility matrix to the project’s docs so the next person doesn’t discover the gap by trial and error. Minikube’s own GitHub issues are full of exactly these driver-specific reports sitting unresolved for lack of someone who reproduces and narrows them down.
Key Takeaways
- Minikube isolates the cluster inside a VM or container, trading startup speed and resource overhead for isolation closer to a real cloud node
- Profiles let you run multiple independent, differently-versioned clusters side by side — a genuine capability MicroK8s doesn’t have
LoadBalancerservices needminikube tunnelorminikube service— there’s no cloud provider underneath to satisfy the request automatically- Driver choice has real consequences: VM drivers need nested virtualization support that not every host or CI runner provides, and feature parity across drivers is uneven
- The clearest contribution opportunity is narrowing and documenting (or fixing) specific driver feature-parity gaps — achievable without deep hypervisor expertise
What’s Next
EP01 and EP02 covered MicroK8s and Minikube individually. EP03 puts them head-to-head against k3s — the third major lightweight Kubernetes option — on the criteria that actually matter when picking one: resource footprint, HA story, and how much you’re willing to trade control for convenience.
Next: EP03 — k3s vs MicroK8s vs Minikube: Which Lightweight Kubernetes Fits Your Use Case
Get EP03 in your inbox when it publishes → linuxcent.com/subscribe