You cannot learn Kubernetes from docs alone. You need a real cluster to practice on. The good news: you can run a full Kubernetes cluster on your laptop for free.
In this tutorial, you will install Kubernetes locally, run your first pod, and learn the essential kubectl commands.
Prerequisites: Docker must be installed. If not, see Docker Tutorial #2: How to Install Docker.
Options for Running Kubernetes Locally
There are four main ways to run Kubernetes on your laptop:
| Tool | Best for | Startup time | Multi-node |
|---|---|---|---|
| minikube | Beginners, learning | ~1 min | Yes (with driver) |
| kind | CI/CD, fast testing | ~30 sec | Yes |
| k3s | Lightweight, Raspberry Pi | ~30 sec | Yes |
| Docker Desktop K8s | Quick experiments | ~2 min | No |
For this tutorial, we focus on minikube (best for beginners) and kind (best for CI and speed). Both are free and open-source.
Step 1: Install kubectl
kubectl is the Kubernetes CLI. You need it regardless of which local tool you choose.
macOS (Homebrew):
brew install kubectl
Linux (apt):
sudo apt-get update
sudo apt-get install -y kubectl
Windows (winget):
winget install Kubernetes.kubectl
Verify the installation:
kubectl version --client
You should see the client version printed. The server version will show “connection refused” for now — that is expected since we have not started a cluster yet.
Option A: Install minikube
minikube runs a single-node Kubernetes cluster inside a VM or container on your machine. It comes with a dashboard, addon system, and is the friendliest option for beginners.
macOS (Homebrew):
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):
winget install Kubernetes.minikube
Start a minikube Cluster
minikube start
minikube will download the Kubernetes node image and start a cluster. This takes about 1 minute the first time.
* minikube v1.35.0 on Darwin 15.4.0 (arm64)
* Using the docker driver
* Starting "minikube" primary control-plane node in "minikube" cluster
* Pulling base image v0.0.45 ...
* Creating docker container (CPUs=2, Memory=4000MB) ...
* Done! kubectl is now configured to use "minikube" cluster and "default" namespace
Verify the cluster is running:
kubectl cluster-info
kubectl get nodes
Expected output:
NAME STATUS ROLES AGE VERSION
minikube Ready control-plane 30s v1.35.0
minikube Dashboard
One of minikube’s best features is the built-in dashboard:
minikube dashboard
This opens a web UI in your browser where you can see Pods, Deployments, Services, and more. Very useful for learning.
Useful minikube Commands
# Start the cluster
minikube start
# Stop the cluster (frees CPU/RAM)
minikube stop
# Delete the cluster entirely
minikube delete
# Check cluster status
minikube status
# Enable an addon (e.g., metrics-server)
minikube addons enable metrics-server
# List available addons
minikube addons list
# SSH into the minikube node
minikube ssh
Tip: Always run minikube stop when you are done. A running minikube cluster uses ~2GB of RAM in the background.
Option B: Install kind
kind (Kubernetes IN Docker) runs Kubernetes nodes as Docker containers. It is faster than minikube and excellent for CI/CD pipelines. It also supports multi-node clusters easily.
macOS (Homebrew):
brew install kind
Linux:
curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind
Windows (winget):
winget install Kubernetes.kind
Create a kind Cluster
kind create cluster --name mycluster
Creating cluster "mycluster" ...
* Ensuring node image (kindest/node:v1.35.0) ...
* Preparing nodes ...
* Writing configuration ...
* Starting control-plane ...
* Installing CNI ...
* Installing StorageClass ...
Set kubectl context to "kind-mycluster"
Cluster is now ready!
Verify:
kubectl get nodes
NAME STATUS ROLES AGE VERSION
mycluster-control-plane Ready control-plane 60s v1.35.0
Multi-node kind Cluster
kind makes it easy to create a cluster with multiple nodes. Create a config file:
# kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker
kind create cluster --name mycluster --config kind-config.yaml
kubectl get nodes
NAME STATUS ROLES AGE
mycluster-control-plane Ready control-plane 90s
mycluster-worker Ready <none> 60s
mycluster-worker2 Ready <none> 60s
Useful kind Commands
# List clusters
kind get clusters
# Delete a cluster
kind delete cluster --name mycluster
# Load a local Docker image into the cluster
kind load docker-image myapp:1.0 --name mycluster
Understanding kubectl Contexts
When you have multiple clusters (minikube, kind, a remote cluster), kubectl needs to know which one to talk to. This is managed through contexts.
# List all contexts
kubectl config get-contexts
# Switch to a context
kubectl config use-context minikube
kubectl config use-context kind-mycluster
# Show current context
kubectl config current-context
Example output of get-contexts:
CURRENT NAME CLUSTER AUTHINFO
docker-desktop docker-desktop docker-desktop
* minikube minikube minikube
kind-mycluster kind-mycluster kind-mycluster
The * shows your active context. Every kubectl command runs against this cluster.
Run Your First Pod
Let us run a simple nginx web server as a Pod:
kubectl run nginx --image=nginx:alpine --port=80
Check that the Pod is running:
kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 15s
Get more details:
kubectl describe pod nginx
Access the nginx server using port-forward:
kubectl port-forward pod/nginx 8080:80
Now open http://localhost:8080 in your browser. You will see the nginx welcome page.
Press Ctrl+C to stop port-forwarding.
Essential kubectl Commands
Here are the commands you will use most often:
# Get resources
kubectl get pods
kubectl get deployments
kubectl get services
kubectl get nodes
# Get all resources in all namespaces
kubectl get pods -A
# Describe a resource (detailed view)
kubectl describe pod mypod
kubectl describe node minikube
# View logs
kubectl logs mypod
kubectl logs mypod -f # follow logs in real-time
kubectl logs mypod -c mycontainer # specific container in pod
# Execute a command inside a running pod
kubectl exec -it mypod -- /bin/sh
# Apply a YAML manifest
kubectl apply -f manifest.yaml
# Delete a resource
kubectl delete pod nginx
kubectl delete -f manifest.yaml
# Watch resources update in real-time
kubectl get pods -w
Namespaces
Kubernetes uses namespaces to divide cluster resources between users and teams. Think of them as virtual sub-clusters.
# List all namespaces
kubectl get namespaces
# List pods in the kube-system namespace (core Kubernetes components)
kubectl get pods -n kube-system
# Create a namespace
kubectl create namespace myapp
# Run a command in a specific namespace
kubectl get pods -n myapp
By default, kubectl commands target the default namespace. Use -n <namespace> to target another one.
Clean Up
Delete the nginx pod we created:
kubectl delete pod nginx
When you are done learning for the day:
# If using minikube
minikube stop
# If using kind
kind delete cluster --name mycluster
Common Mistakes
Using Docker Desktop’s built-in Kubernetes
Docker Desktop includes Kubernetes with a basic dashboard view. However, it lacks minikube’s addon system and the flexible multi-node configurations that kind provides. For deeper learning and CI/CD, prefer minikube or kind.
Wrong context
If kubectl commands fail or show unexpected results, check your context first:
kubectl config current-context
It is easy to accidentally run commands against the wrong cluster.
Forgetting to stop minikube
minikube runs in the background and uses CPU and RAM. Always minikube stop when you are done. kind clusters are lighter since they are just Docker containers.
What’s Next?
Your cluster is running. Now learn the three core Kubernetes objects: Pods, Deployments, and Services.
Next: Kubernetes Tutorial #3: Pods, Deployments, and Services