Get a Cluster to Practice On¶
Assumes: you can use a terminal and have Docker (or Podman) installed. Nothing about Kubernetes yet.
Every other page on this site gives you kubectl commands. This page gets you a cluster to run them against, on your own machine, in about five minutes. Nothing here costs money and nothing touches a cloud account.
1. Install kubectl¶
kubectl is the command-line client that talks to a cluster's API server. Install it however your platform prefers:
# macOS
brew install kubectl
# Linux (x86_64)
curl -LO "https://dl.k8s.io/release/$(curl -Ls https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
# Windows
winget install -e --id Kubernetes.kubectl
Verify:
2. Create a cluster with kind¶
kind ("Kubernetes in Docker") runs a real cluster inside Docker containers. It is the fastest option and the closest to a normal cluster.
# macOS
brew install kind
# Linux / anything with Go toolchain-free install
curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64
chmod +x ./kind && sudo mv ./kind /usr/local/bin/kind
kind create cluster --name learn
That last command downloads a node image, boots a single-node cluster, and writes the connection details into your kubeconfig (~/.kube/config) so kubectl finds it automatically.
Alternatives: minikube (minikube start) runs a VM or container-based cluster with add-ons like an Ingress controller and a dashboard, and k3d (k3d cluster create learn) runs the lightweight k3s distribution in Docker. Any of the three works for everything on this site.
3. Verify it¶
You should see one node with status Ready:
If it says NotFound or the connection is refused, the cluster did not come up - check that Docker is running and re-run kind create cluster.
4. Run something¶
Create a Deployment (three nginx pods, kept alive for you) and put a Service in front of it:
kubectl create deployment web --image=nginx:1.27 --replicas=3
kubectl expose deployment web --port=80 --target-port=80
Watch what Kubernetes actually did:
You asked for three replicas, and the Deployment created a ReplicaSet, which created three Pods, which the scheduler placed on your node. You never told it to do any of that - that is the reconciliation model from the Overview working in front of you.
5. Reach it¶
The Service has a virtual IP that only exists inside the cluster, so forward a local port to it:
Open http://localhost:8080 and you get the nginx welcome page. Press Ctrl+C to stop forwarding.
Now try the thing that makes Kubernetes click. In a second terminal:
You deleted all three pods. The ReplicaSet notices the gap between desired (3) and actual (0) and creates replacements immediately. You did not ask for that either.
Cleaning up¶
kubectl delete deployment web
kubectl delete service web
# or throw the whole cluster away
kind delete cluster --name learn
Deleting and recreating the cluster takes under a minute, so treat it as disposable. Breaking it is the point.
Check Yourself¶
You ran kubectl create deployment web --replicas=3 and the command returned instantly. Were three pods running at that moment?
Almost certainly not. The command only wrote a Deployment object to the API server. The Deployment controller then created a ReplicaSet, the ReplicaSet created Pods, the scheduler assigned them to a node, and the kubelet pulled the nginx image and started the containers - all after your command returned. Success from kubectl means "intent recorded", not "workload running".
Why did deleting all three pods not leave you with zero pods?
Nothing in Kubernetes remembers that you issued a delete. The ReplicaSet controller only ever compares desired state (3 replicas) against what it observes (0 pods) and creates the difference. Deleting pods does not change the desired state, so the gap is immediately refilled.
You closed the terminal running kubectl port-forward and localhost:8080 stopped working. Did something break in the cluster?
No. port-forward is a tunnel maintained by your local kubectl process, not a cluster feature. The Service and pods are untouched. A ClusterIP Service is only reachable from inside the cluster, which is why you needed the tunnel at all - Ingress and LoadBalancer Services are the real answers for outside traffic.
What would you expect kubectl get nodes to show on a kind cluster with one node, and why does that differ from production?
One node named <cluster>-control-plane with the control-plane role, running both the control plane and your workloads. Production clusters normally taint control-plane nodes so application pods never land on them, and add separate worker nodes. Single-node local clusters skip that so your pods have somewhere to run.
Related Concepts¶
- Learning Paths - where this page sits in your track
- Kubernetes Overview - the model behind what you just watched happen
- Pods and Deployments - what you just created, in detail
- Kubectl Cheat Sheet - the commands you will use most
- Troubleshooting - when a pod does not come up
Beginner track - step 2 of 12. Next: Pods and Deployments. Back to the track overview.