Installing Kubernetes with Minikube
Set up a local Kubernetes cluster with minikube. Drivers, sizing, add-ons for Ingress and metrics, minikube tunnel, and using its Docker daemon for fast builds.
Minikube runs a local Kubernetes cluster in a VM or a Docker container. Its distinguishing feature is the add-on system: Ingress, metrics-server and a dashboard are one command each, rather than a Helm install and a configuration file.
Install
# macOS
brew install minikube
# Linux
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
# Windows
winget install Kubernetes.minikube
You also need a driver. Docker is the usual choice and works everywhere.
Start a cluster
minikube start --cpus=4 --memory=8192
๐ minikube v1.34.0 on Darwin 15.0
โจ Using the docker driver based on existing profile
๐ Done! kubectl is now configured to use "minikube" cluster
Set --cpus and --memory explicitly. The defaults of 2 CPUs and 2GB are enough for a bare cluster and not enough once you add an ingress controller or anything else. Insufficient cpu on a fresh minikube is nearly always this.
kubectl get nodes
minikube status
Other options worth knowing at start time:
minikube start --kubernetes-version=v1.31.2 # match a target cluster
minikube start --driver=docker # pick the driver explicitly
minikube start --nodes=3 # multi-node
A multi-node cluster is worth creating. Single-node hides every scheduling, affinity and anti-affinity problem you will eventually meet in a real cluster.
Add-ons
This is why people choose minikube.
minikube addons list
minikube addons enable ingress
minikube addons enable metrics-server
| Add-on | What it gives you |
|---|---|
ingress | An NGINX ingress controller, ready to use |
metrics-server | Makes kubectl top and the HPA work |
dashboard | The web UI |
registry | A local image registry inside the cluster |
csi-hostpath-driver | Dynamic PersistentVolume provisioning |
metrics-server is the one to enable immediately, without it kubectl top fails and every HorizontalPodAutoscaler reports <unknown>.
minikube dashboard
Reaching your services
A local cluster has no cloud load balancer, so there are three ways in.
NodePort, with a helper to give you the URL:
minikube service payments-api --url
http://192.168.49.2:31847
LoadBalancer, which needs minikube tunnel running in a separate terminal:
minikube tunnel
Without it, LoadBalancer Services sit at <pending> forever. The tunnel creates a route to the cluster and assigns them addresses, and it usually asks for a password because it modifies network routes.
Ingress, once the add-on is enabled:
minikube ip # e.g. 192.168.49.2
# Add to /etc/hosts
192.168.49.2 payments.local
Or skip all of it for quick checks:
kubectl port-forward service/payments-api 8080:80
Building images without a registry
Minikube's cluster cannot see your host's Docker images. Rather than pushing to a registry, point your shell at minikube's own Docker daemon:
eval $(minikube docker-env)
docker build -t myapp:dev .
The image is now built inside the cluster's daemon and immediately available. Set imagePullPolicy: IfNotPresent, with Always, or an unpinned latest tag which defaults to Always, the kubelet tries the registry anyway and fails.
eval $(minikube docker-env -u) # switch back to your normal Docker
The alternative, if you prefer not to change your shell environment:
minikube image load myapp:dev
Profiles
Several independent clusters, useful for keeping projects apart or testing across Kubernetes versions:
minikube start -p payments --cpus=4 --memory=8192
minikube start -p legacy --kubernetes-version=v1.28.0
minikube profile list
minikube profile payments # set the default
kubectl config use-context payments
Each profile is a separate VM or container with its own resources. They are not free, so delete the ones you are not using.
Housekeeping
minikube stop # keep the cluster, free the resources
minikube start # resume it
minikube delete # remove it entirely
minikube delete --all # every profile
stop then start is much faster than recreating, and preserves everything you deployed.
When something is genuinely wrong, minikube delete && minikube start is usually quicker than debugging the local cluster itself.
minikube logs # cluster component logs
minikube ssh # shell onto the node
Quick reference
| Task | Command |
|---|---|
| Start sized properly | minikube start --cpus=4 --memory=8192 |
| Specific version | minikube start --kubernetes-version=v1.31.2 |
| Multi-node | minikube start --nodes=3 |
| Enable an add-on | minikube addons enable ingress |
| Service URL | minikube service <name> --url |
| Make LoadBalancer work | minikube tunnel |
| Node IP | minikube ip |
| Build into the cluster | eval $(minikube docker-env) |
| Load a built image | minikube image load <image> |
| New profile | minikube start -p <name> |
| Stop / delete | minikube stop / minikube delete |
Key takeaways
- Always pass
--cpusand--memory. The 2GB default causes scheduling failures as soon as you add anything. - Add-ons are the reason to pick minikube:
ingressandmetrics-serverin one command each. minikube tunnelis what makesLoadBalancerServices work. Without it they stay<pending>.eval $(minikube docker-env)builds straight into the cluster, withimagePullPolicy: IfNotPresent.- Create a multi-node cluster. Single-node hides scheduling behaviour you need to understand.
- Profiles give you independent clusters, each consuming real resources.
minikube stopbeatsdeletewhen you just want the resources back.
Check your understanding
A locally built image that will not run
You run eval $(minikube docker-env), build myapp:dev, and deploy it. The Pod still reports ImagePullBackOff. What is the most likely cause?
Pods pending on a fresh cluster
Immediately after minikube start with default settings, enabling the ingress add-on leaves Pods Pending with "Insufficient cpu". What is wrong?
Frequently Asked Questions
How much memory and CPU should I give minikube?
At least 4 CPUs and 8GB if your machine allows it, passed as minikube start --cpus=4 --memory=8192. The defaults of 2 CPUs and 2GB are enough for an empty cluster and run out as soon as you enable an ingress controller or deploy a few workloads, producing Insufficient cpu errors that look like a misconfiguration but are simply a lack of capacity. The setting only applies at creation, so changing it means deleting and recreating the cluster.
How do I access a service running in minikube?
For a NodePort Service, minikube service <name> --url prints a working URL. For a LoadBalancer Service you need minikube tunnel running in a separate terminal, otherwise the external IP stays <pending> indefinitely. With the ingress add-on enabled, minikube ip gives the address to point a hosts-file entry at. For a quick check none of that is necessary, kubectl port-forward service/<name> 8080:80 works immediately.
Why is my LoadBalancer Service stuck pending in minikube?
There is no cloud provider to create a load balancer, so nothing ever assigns the external IP. minikube tunnel fills that role by creating a network route into the cluster and assigning addresses to LoadBalancer Services. It has to keep running in its own terminal, and it usually prompts for a password because it modifies system routes.
How do I use a locally built Docker image in minikube?
Run eval $(minikube docker-env) to point your shell at minikube's own Docker daemon, then build normally. The image lands directly in the cluster with no registry involved. Set imagePullPolicy: IfNotPresent on the container, since Always, which is also the default for an unpinned or latest tag, makes the kubelet attempt a registry pull that fails. eval $(minikube docker-env -u) switches your shell back. Alternatively, minikube image load myapp:dev copies an already-built image in.
What is the difference between minikube stop and minikube delete?
stop shuts the cluster down while preserving its state, so minikube start brings everything back including your deployments. Much faster than recreating. delete removes the cluster and all its data permanently. Use stop to reclaim memory and CPU between work sessions, and delete when you want a clean slate or when troubleshooting the local cluster itself has become slower than rebuilding it.
Can I run more than one minikube cluster?
Yes, using profiles: minikube start -p payments and minikube start -p legacy --kubernetes-version=v1.28.0 create independent clusters, each with its own kubectl context. minikube profile list shows them and minikube profile <name> sets the default for minikube commands. Each profile is a separate VM or container consuming real CPU and memory, so delete profiles you are not actively using.