Getting started with Kubernetes for local development. I develop on a Mac, but most of this translates cleanly to Windows and Linux.
This started as my personal development notes, written to get co-workers up to speed quickly. If you spot an error, open an issue or a pull request.
§2026 Update
This post is from 2018, when a local cluster meant minikube on top of VirtualBox and Kubernetes was at v1.9. The mental model below has held up well: a cluster has nodes, a node runs pods, a pod runs containers. The core kubectl verbs still work the way they did. But the toolchain underneath moved enough that a few of the original commands will either fail or behave differently today. Here is what changed and what I run now.
The big one: kubectl run no longer creates a Deployment. As of Kubernetes 1.18 it creates a single Pod and nothing more. The generator flags that used to spin up a Deployment were removed. If you want something managed and replicated, use kubectl create deployment (shown below) or a YAML manifest. kubectl run is now for one-off pods, like a quick debug shell.
heapster is gone and metrics-server replaced it. The old minikube addons enable heapster no longer exists. For kubectl top and autoscaling metrics, enable metrics-server instead.
CoreDNS replaced kube-dns. Cluster DNS is served by CoreDNS now and has been the default for years. You will not see a kube-dns addon on a current minikube.
You no longer need VirtualBox. minikube defaults to the Docker driver on most machines, so a container runtime is usually all you need. You can still pick a driver explicitly with --driver (docker, podman, qemu, and others). The old VirtualBox path works but is no longer the default.
The sample images moved. Google retired gcr.io/google_containers. Images live under registry.k8s.io now, and the official hello-world tutorial uses agnhost instead of echoserver.
minikube is also no longer the only easy option. It is still a great choice and the most batteries-included. But the local-cluster field filled out: kind (built by the Kubernetes project to test Kubernetes itself), k3d (Rancher’s lightweight k3s wrapped in Docker, noticeably faster to start), Docker Desktop’s built-in Kubernetes, and Rancher Desktop (k3s with a GUI). If startup speed matters to you, k3d is hard to beat. If you want maximum fidelity to a “real” cluster, kind. For a guided, addon-rich experience, minikube. I still reach for minikube when I want the dashboard and addons without thinking about it.
The walkthrough below is updated to current commands. The original 2018 session is preserved at the end as a snapshot.
The article continues below. The 2026 Update above summarizes what changed; the walkthrough that follows has been updated to current commands.
§Deeper Reading and Resources
- Official Kubernetes Tutorials
- Kubernetes The Hard Way by Kelsey Hightower, for anyone who wants to understand how every piece fits together before running a production cluster
- killercoda Kubernetes scenarios, browser-based interactive labs (the spiritual successor to the old Katacoda playgrounds)
The Lynda courses I originally linked here are gone; Lynda became LinkedIn Learning. If you are paying for a course, check the publication date and the Kubernetes version it targets before you commit, the platform churns fast enough that a three-year-old course is mostly history.
§Prerequisites
- Install Docker Desktop or Rancher Desktop, either gives you a container runtime for the default driver
- Install kubectl
- Install minikube
VirtualBox is optional now and only needed if you specifically want the virtualbox driver.
§Spin Up a Local Cluster
# start a cluster using the default driver (Docker on most machines)
minikube start
# or name the driver explicitly
minikube start --driver=docker
# enable metrics so kubectl top works (heapster's replacement)
minikube addons enable metrics-server
# open the dashboard in a browser
minikube dashboard
§Check Cluster Status
These commands are unchanged from 2018 and still the first things I run:
# are we running a cluster?
kubectl cluster-info
# we should have a minikube node
kubectl get nodes
# resource usage (needs the metrics-server addon enabled)
kubectl top nodes
§Architecture
Read Kubernetes Basics for a fuller picture, but the short version still holds:
- A Cluster has Nodes
- A Node runs Pods
- A Pod runs containers and mounts volumes
§Create a Deployment
Run a “hello world” using the current sample image. Note kubectl create deployment, not kubectl run, since we want a managed Deployment:
# create a Deployment from the official sample image
kubectl create deployment hello-node \
--image=registry.k8s.io/e2e-test-images/agnhost:2.53 \
-- /agnhost netexec --http-port=8080
# expose it as a NodePort service
kubectl expose deployment hello-node --type=NodePort --port=8080
# get a reachable URL
minikube service hello-node --url
Open the URL it prints. To tear it down:
kubectl delete service hello-node
kubectl delete deployment hello-node
§Useful Commands
| Command | Description |
|---|---|
kubectl get pods -o wide | Get information about all running pods in the default namespace |
kubectl get pods -o wide --namespace=test | Get information about all running pods in the test namespace |
kubectl describe pod <pod> | Describe one pod |
kubectl expose pod <pod> --port=2701 --name=api | Expose the port of a pod (creates a new service) |
kubectl attach <pod> -i | Attach to a pod |
kubectl exec <pod> -- command | Execute a command in the pod |
kubectl label pods <pod> mylabel=fun | Add a new label to a pod |
kubectl run -i --tty alpine --image=alpine --restart=Never -- sh | Run a throwaway shell in a one-off pod |
§Port Forwarding / Local Development
Check out kubefwd for a command line utility that bulk forwards services of one or more namespaces to your local workstation, so your local code can talk to in-cluster services by their real names.
§Original 2018 Walkthrough
Preserved as a snapshot. The versions and addon list below are historical, minikube was at v0.25 and Kubernetes at v1.9, the Docker driver did not exist yet, and heapster and kube-dns were still the defaults.
$ minikube version
minikube version: v0.25.0
$ minikube start
Starting local Kubernetes v1.9.0 cluster...
Starting VM...
Getting VM IP address...
Moving files into cluster...
Setting up certs...
Connecting to cluster...
Setting up kubeconfig...
Starting cluster components...
Kubectl is now configured to use the cluster.
Loading cached images from config file.
$ minikube addons list
- addon-manager: enabled
- coredns: disabled
- dashboard: enabled
- default-storageclass: enabled
- efk: disabled
- freshpod: disabled
- heapster: disabled
- ingress: disabled
- kube-dns: enabled
- registry: disabled
- registry-creds: disabled
- storage-provisioner: enabled
# enable heapster for CPU and mem
$ minikube addons enable heapster
heapster was successfully enabled
# the original hello world, using the now-retired image registry
$ kubectl run hello-minikube --image=gcr.io/google_containers/echoserver:1.4 --port=8080
deployment "hello-minikube" created
$ kubectl expose deployment hello-minikube --type=NodePort
service "hello-minikube" exposed
$ minikube service hello-minikube --url
http://192.168.99.100:31923