Day 1: Your First Cluster
kubectl get nodes prints one node, STATUS Ready, on your own machine. That is the whole point of today.
Why this matters for your mission
You want to learn Kubernetes. k3s on this box is a real, standard Kubernetes cluster, and everything you learn on it transfers to any cluster. Your homelab services (PaperMC, Grafana, Nextcloud) will become useful practice targets along the way, but today is about the platform itself. Until the API server answers, none of the rest of the week exists.
You already know more than you think
Compose is a degenerate Kubernetes. That table in the README is the bridge:
restart: always→ a Deployment controller keeps desired statedocker ps→kubectl get podsdocker compose scale→kubectl scale deploymenthealthcheck:in compose → liveness / readiness probes
So today is not a new world. It is your world with a control plane bolted on.
The one mental model to internalize today
Kubernetes is a declarative control loop. You declare desired state (a
manifest); controllers reconcile reality toward it forever. There is no
“start this container” command. When you kubectl delete pod, the
Deployment controller sees 2 of 3 replicas and immediately creates a
replacement. Nobody “restarts” anything; desired state is reconciled.
Do this now (real commands, on your box)
Three steps, each with a verify. Follow 10.11 - Install and First Cluster in detail; the recap is here.
Step 1 · Enable k3s on NixOS
On your machine the k3s service already exists but is inactive (probe found it). You need the module enabled with Traefik and servicelb disabled, because Caddy owns host ports 80/443:
{ pkgs, ... }:
{
services.k3s = {
enable = true;
role = "server";
extraFlags = ''
--write-kubeconfig-mode 644
--disable traefik
--disable servicelb
'';
};
environment.systemPackages = with pkgs; [ kubectl ];
}
Then rebuild: sudo nixos-rebuild switch --flake ~/nix#<your-host>
Step 2 · Verify the API is alive
systemctl status k3s # active (running)
kubectl get nodes -o wide # one node, STATUS=Ready
kubectl get pods -A # coredns + metrics-server + local-path
kubectl cluster-info # control plane reachable
Step 3 · First pod, first deployment (the day-1 exercise)
kubectl run hello --image=nginx:alpine # throwaway smoke test
kubectl get pods; kubectl logs hello; kubectl delete pod hello
kubectl create deployment hello --image=nginx:alpine --replicas=2
kubectl get deployments,replicasets,pods
kubectl port-forward deployment/hello 8080:80 # open http://localhost:8080
kubectl exec -it deployment/hello -- bash
kubectl logs deployment/hello --tail=20
kubectl delete deployment hello
kubectl apply -f. That is the declarative habit your
mission depends on.
Check your understanding
One attempt per question, then the feedback. Say the answer in your head before clicking.
You delete a pod that a Deployment owns. What happens next, and why?
Why are Traefik and servicelb disabled in this setup?
What is the smallest unit Kubernetes schedules, and what assumption should you make about it?
When you are done
kubectl get nodesshows Ready.- You ran a deployment, port-forwarded it, exec’d in, and read its logs.
- You can say what happens when a Deployment-owned pod dies, in one breath.
Read next
- 10.12 - Core Concepts — the full mental model behind what you just did.
- 10.31 - kubectl Cheatsheet — the only verbs you need this week.
Primary source for this lesson
Chapter 1 of Kubernetes in Action, 2nd ed (Lukša) covers exactly this ground. The k3s install details are in docs.k3s.io. Read one of them today if you can.