Sign in
← Kubernetes locally
9 min · easy · Lesson 5 of 8

minikube: drivers, ports, and addons

How minikube differs from kind and k3d, which Kubernetes version it actually gives you, and why ports deserve their own section here.

minikube is the oldest local Kubernetes tool still actively maintained, and it works differently from kind or k3d. Those two do exactly one thing: run nodes as containers. minikube picks where to run the node from a whole list of options: a Docker container, a KVM virtual machine, or a virtual machine through the native hypervisor on macOS or Windows.

Why

People reach for minikube when they want one familiar tool on any system, plus ready-made cluster add-ons. Ingress, metrics-server, or an image registry turn on with a single command, with no manifests to install by hand. One more reason: of the three tools, only minikube can run a node inside a virtual machine, which means a separate kernel.

The price is speed. In the official time-to-k8s benchmark (v1.36.0, linux/amd64), minikube comes up in 50.8 seconds, against 33.0 for kind and 19.9 for k3d.

Concepts

Driver - the way minikube creates the node. Chosen with the --driver flag: docker makes the node a container, kvm2, vfkit, or hyperv make it a virtual machine.

A virtual machine costs more in resources, but gives you a real kernel and real isolation from the host. A container node starts faster, but shares the kernel with the host, with all the limits that brings.

Profile - a separate cluster with its own name and state. Set with the -p flag; without it, every command works against the minikube profile. You can have several profiles at once.

Addon - a ready-made cluster component that minikube installs and updates itself: minikube addons enable <name>.

minikube version and Kubernetes version

The current release is v1.39.0, from September 1, 2026. By default it brings up Kubernetes v1.37.0; the supported range is v1.28.0 to v1.37.0. You can check your binary's range without a cluster:

minikube config defaults kubernetes-version

The command prints a list of versions, newest on top.

The Kubernetes version is baked into the minikube binary, not fetched from the website. That matters, because the documentation site builds from the master branch and can run ahead of the release. That's exactly what happened in the summer of 2026, before v1.39.0 shipped: the site already described v1.37.0 as the default, while the released v1.38.1 brought up v1.35.1 and couldn't go above v1.35.1.

If you need a specific version, set it with a flag:

minikube start --kubernetes-version=v1.33.0

If you give only the minor version, --kubernetes-version=v1.35, minikube picks the latest patch it knows (v1.39.0 picks 1.35.8). The value stable means the default version, that is v1.37.0 for v1.39.0. minikube won't start a version outside its range: v1.38.0 gets you K8S_NEW_UNSUPPORTED, v1.20.0 gets K8S_OLD_UNSUPPORTED.

To see what you actually got, check the cluster itself:

minikube kubectl -- get nodes

The VERSION column shows the version the kubelet started with.

Drivers

The actual default on every OS is docker. If Docker is installed, minikube uses it.

When you don't want to install Docker, there are VM-based options:

The hyperkit driver is deprecated: its builds were dropped from releases in v1.38.0, so don't count on it anymore. VirtualBox on Apple Silicon didn't work for a long time; as of v1.39.0 it's supported with VirtualBox 7.1 or newer.

A separate note on Windows: the combination of WSL2 with the docker driver is marked experimental by the project.

Starting with v1.39.0, the node runs containerd by default, not Docker. Images built by Docker on the host aren't automatically visible inside the node; load them with minikube image load <image>.

Resources

The minimum to run is 2 CPU, 2 GB of free memory, 20 GB of disk.

minikube allocates memory to the cluster itself: about 25% of the host's memory, but not less than 3072 MB and not more than 6144 MB. With --nodes N, that 25% is first split between the nodes, and each node still gets at least 3072 MB. Set your own number with the --memory flag (--memory=4g or --memory=4096); minikube won't accept less than 1800 MB:

X Exiting due to RSRC_INSUFFICIENT_REQ_MEMORY: Requested memory allocation 1024MiB is less than the usable minimum of 1800MB

The --memory flag can silently do nothing. If the host is missing the needed cgroup controllers, you won't get an error: the limit just won't apply, and the cluster will take as much memory as it can.

Installation

brew install minikube                                                                          # macOS
curl -LO https://github.com/kubernetes/minikube/releases/download/v1.39.0/minikube-linux-amd64  # Linux x86_64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
curl -LO https://github.com/kubernetes/minikube/releases/download/v1.39.0/minikube-linux-arm64  # Linux arm64
sudo install minikube-linux-arm64 /usr/local/bin/minikube
winget install Kubernetes.minikube                                                             # Windows

In WSL2, minikube installs inside the Linux distribution, same as on plain Linux.

On Apple Silicon you need the arm64 binary specifically, minikube-darwin-arm64. The reason is concrete: the amd64 binary will run under Rosetta and seem to work, but the docker driver ends up Unhealthy. Homebrew picks the right build on its own; a manually downloaded file does not. Check the binary's architecture on macOS with: file "$(command -v minikube)"; the output should say arm64.

Startup and lifecycle

minikube start
minikube start --kubernetes-version=v1.33.0 --driver=docker
minikube start --nodes 2 -p multinode-demo
minikube stop
minikube delete

stop stops the cluster and keeps its state, delete removes it for good. Both commands work against the minikube profile without -p; add -p <name> for your own profile. minikube profile list shows all profiles.

Before a real start, you can check the flags without creating a cluster:

minikube start --dry-run -p izi-demo --driver=docker --kubernetes-version=v1.33.0
* [izi-demo] minikube v1.39.0 on Darwin 15.0 (arm64)
* Using the docker driver based on user configuration
* Using Docker Desktop driver with root privileges
* dry-run validation complete!

--dry-run catches typos in flags, a Kubernetes version outside the range, a --memory value that's too small, and a broken --ports. It doesn't download the node image and doesn't create a cluster.

You don't have to install kubectl separately; minikube carries its own:

minikube kubectl -- get po -A

The double dash separates minikube's arguments from kubectl's. Everything after it goes through as is.

How ports work

Docker virtual machine your Mac curl 192.168.49.2 minikube node 192.168.49.2 Pod web · 8080 curl hangs minikube service --url
The node's IP stays behind the virtual machine boundary. Only the forwarded port gets out.

With the docker driver, the node lives inside a container. On Linux, Docker's network is reachable from the host directly, and the node's IP responds. On macOS, Windows, and in WSL2, Docker runs on top of a virtual machine, so the node's IP is unreachable from the host. The minikube ip command prints an address, curl against it hangs, and the cluster isn't the reason.

For a NodePort Service there's a ready-made workaround:

minikube service web --url

The command prints an address like http://127.0.0.1:<port> and keeps the forward running as long as the process is alive. Close the terminal and the forward is gone.

For a LoadBalancer Service you need a tunnel:

minikube tunnel
minikube tunnel --cleanup

Without it, EXTERNAL-IP stays <pending> forever. The tunnel sets up routing on the host, so it asks for root privileges. On Windows, ports below 1024 also need elevated privileges. On macOS, the tunnel with the docker driver has a limitation: it doesn't resolve Kubernetes DNS.

A third option: pin the forward when you create the cluster.

minikube start --driver=docker --ports=127.0.0.1:9090:30090

The --ports format is the same as docker run -p: host address, host port, node-container port. Without an address (--ports=9090:30090), the port opens on every interface on the machine, and the app is visible to anyone on your Wi-Fi network. The flag only works with the docker and podman drivers, is set once at startup, and is the closest thing to how kind opens ports.

MethodFor which ServiceHow long it lastsRoot privileges
minikube service web --urlNodePortwhile the process runsno
minikube tunnelLoadBalancerwhile the process runsyes
--ports=127.0.0.1:9090:30090NodePortthe cluster's whole lifetimeno

Addons

Extra components turn on with a single command; minikube addons list gives the full list.

minikube addons enable ingress
minikube addons enable metrics-server

The ingress addon in v1.39.0 installs ingress-nginx 1.15.1. That's the last version: the kubernetes/ingress-nginx repository was archived on March 24, 2026 and switched to read-only, with no more releases, bugfixes, or security patches coming. For learning on a laptop that's tolerable: the cluster doesn't face the outside world. Don't carry this setup further: the official Kubernetes recommendation is to pick a Gateway API implementation. v1.39.0 added a traefik addon, which installs Traefik through Helm.

metrics-server is simpler. In kind, after installing it you have to patch it with the --kubelet-insecure-tls flag to work with kubelet's self-signed certificate; in minikube the addon already starts with that flag. kubectl top just works, nothing to fix.

Storage

The StorageClass is named standard and marked default. The provisioner is k8s.io/minikube-hostpath, minikube's own implementation, not a CSI driver.

In a multi-node cluster, the host-path provisioner does not work. The volume gets created on one node, and the Pod can end up on another. For several nodes you need the separate csi-hostpath-driver addon.

Only data in the /data, /var/lib/minikube, /var/lib/docker, and /tmp/hostpath_pv directories survives a cluster restart. Anything written outside them disappears.

Common mistakes

Trusting the website over the binary. Your minikube version decides the default Kubernetes version, not the documentation homepage. Check minikube config defaults kubernetes-version and the VERSION column on your nodes.

Forgetting the profile. Without -p, a command creates or deletes the minikube profile. If the machine already has a working cluster under that name, minikube delete without -p will take it down.

curl against minikube ip hangs. On macOS, Windows, and in WSL2 that's expected; you need minikube service --url, a tunnel, or --ports.

--ports without an address. The port opens on every interface, not just 127.0.0.1.

amd64 binary on Apple Silicon. The docker driver ends up Unhealthy. Separately: v1.38.0 had a regression where running x86_64 images on Apple Silicon failed with exec format error. It was fixed in v1.38.1 (release notes: "Fix regression cross-arch execution by masking systemd-binfmt"); steer clear of v1.38.0.

IPv6. Not supported, so you can't explore dual-stack on minikube.

What you'll need for the tasks

Both labs run without a lab environment: no cluster gets created, and you barely need any memory. You need bash and Docker 20.10+, running.

Done reading?

Mark the lesson as read to move your track progress forward.

Go through it with an AI agent

The agent explains anything unclear in plain words, gives you 2 labs for this lesson and drills you on interview questions. $49 one-time, lifetime access.

Get access for $49

Tell the agent: use MCP izi, give me lesson k8s-local-05-minikube