All Modules Why K8s Concepts Hands-on Lab Cheat Sheet

Kubernetes Intro

Run your app on a real cluster — that heals and scales itself.

Module 8 · The notes app goes from one machine to a cluster. Free · Local with Minikube.

Beginner+ Orchestration ~60 min

What You'll Learn

By the end of this module you will be able to:

  • Explain what Kubernetes does that Docker Compose can't — and when you actually need it
  • Define the core objects: Cluster, Node, Pod, Deployment, Service
  • Spin up a free local cluster with Minikube and drive it with kubectl
  • Deploy the notes app + database from YAML manifests
  • Watch Kubernetes self-heal a deleted pod and scale to multiple replicas
  • Expose your app and open it in the browser

Prerequisites: Module 7 — Compose. You should understand images, containers, volumes, and env vars.

Why Kubernetes Exists

Compose is perfect for one machine. But what happens in the real world when…

…your container crashes at 3 a.m.?

With Compose, it stays down until a human notices. What if you need 10 copies of your app across 5 servers? What if one server dies? What about rolling out a new version with zero downtime? Compose has no answer. Kubernetes (K8s) does.

Kubernetes is an orchestrator: you declare the desired state ("I want 3 copies of this app, always running"), and K8s constantly works to make reality match — restarting crashed containers, rescheduling them when a server dies, spreading load across machines.

Compose vs. Kubernetes

Docker ComposeKubernetes
ScopeOne machineA cluster of many machines
If a container diesStays deadAuto-restarted
ScalingManual, one hostDeclare replicas, any host
UpdatesRestart (downtime)Rolling, zero-downtime
Best forLocal dev, small appsProduction, scale, HA

Don't be scared of the reputation

K8s is famous for being complex — but the core is just a handful of objects. Today you'll learn the 5 that cover 90% of real use. Everything else builds on them.

The 5 Objects You Must Know

ObjectWhat it isAnalogy
ClusterThe whole system: a control plane + worker machines.The factory
NodeA single machine (VM or physical) that runs your containers.A worker on the floor
PodThe smallest unit K8s runs — wraps one (or more) containers.One running container
DeploymentManages a set of identical pods: keeps N running, handles updates & self-healing.A manager who keeps N workers staffed
ServiceA stable network address + load balancer in front of pods (which come and go).A receptionist with one phone number

The mental model

You almost never create pods directly. You create a Deployment ("keep 3 of these running"), which creates Pods, and a Service gives those pods one stable address — because individual pods get replaced and their IPs change.

Declarative, not imperative

In Compose you say "run this." In K8s you write a YAML file describing the desired state and run kubectl apply. K8s figures out how to get there — and keeps it that way.

Install Minikube & kubectl

Minikube runs a real single-node Kubernetes cluster on your laptop (free). kubectl is the command-line tool you use to talk to any cluster.

Download

Get Minikube from minikube.sigs.k8s.io and kubectl from kubernetes.io/docs/tasks/tools. Minikube needs Docker (from Module 6) as its driver.

Start your cluster and confirm it's alive:

minikube start kubectl get nodes

You should see one node with status Ready — your personal Kubernetes cluster is running. 🎉

Hands-on Lab: Deploy to the Cluster

We'll deploy the notes app + Postgres from Module 7 onto Kubernetes. Work in your notes-app folder and create a k8s/ subfolder for the manifests.

1

Make your image available to the cluster

Minikube has its own image store. Load the notes-app image you built in Module 6 into it:

docker build -t notes-app:1.0 . # rebuild if needed minikube image load notes-app:1.0 # push it into the cluster

In the real world

Normally pods pull images from a registry (Docker Hub from Module 6). minikube image load is a local shortcut so you don't have to push first.

2

Store the DB password in a Secret — k8s/db-secret.yaml

Never put passwords in plain manifests. A Secret holds sensitive values (here Kubernetes encodes them for you with stringData).

apiVersion: v1 kind: Secret metadata: name: db-secret stringData: POSTGRES_USER: notes POSTGRES_PASSWORD: secret POSTGRES_DB: notesdb
3

Deploy Postgres + its Service — k8s/db.yaml

A Deployment runs the database pod; a Service gives it the stable name db so the web app can find it (just like in Compose).

apiVersion: apps/v1 kind: Deployment metadata: name: db spec: replicas: 1 selector: matchLabels: app: db template: metadata: labels: app: db spec: containers: - name: postgres image: postgres:16 envFrom: - secretRef: name: db-secret ports: - containerPort: 5432 --- apiVersion: v1 kind: Service metadata: name: db spec: selector: app: db ports: - port: 5432 targetPort: 5432

Demo simplification

This Postgres pod has no persistent volume, so data resets if the pod restarts — fine for learning. Real stateful databases use a StatefulSet + PersistentVolumeClaim (or a managed cloud DB). We keep it simple to focus on the core objects.

4

Deploy the web app + its Service — k8s/web.yaml

This is the star: replicas: 2 means K8s keeps two copies running. The Service load-balances across them and exposes the app via NodePort.

apiVersion: apps/v1 kind: Deployment metadata: name: web spec: replicas: 2 selector: matchLabels: app: web template: metadata: labels: app: web spec: containers: - name: web image: notes-app:1.0 imagePullPolicy: IfNotPresent env: - name: DATABASE_URL value: postgresql://notes:secret@db:5432/notesdb ports: - containerPort: 5000 --- apiVersion: v1 kind: Service metadata: name: web spec: type: NodePort selector: app: web ports: - port: 5000 targetPort: 5000

How db resolution works

The web pods reach the database at host db — that's the Service name from Step 3. Kubernetes' built-in DNS turns service names into addresses, exactly like Compose did.

5

Apply everything

Point kubectl at the whole folder — it applies every manifest:

kubectl apply -f k8s/ kubectl get pods # watch them go from ContainerCreating -> Running

You should see two web pods and one db pod. The Deployment created them for you.

6

Open the app

Minikube gives you a URL for the NodePort service:

minikube service web

Your browser opens the notes app — now served by a load-balanced pair of pods on your cluster. ✅

The "aha!" moment

The same app from Module 6 now runs as 2 replicas behind a Service on a real Kubernetes cluster — defined entirely in declarative YAML.

7

Watch it self-heal 🔥

This is the magic moment. Delete a running pod and watch Kubernetes replace it within seconds — because the Deployment's desired state says "keep 2 running."

kubectl get pods kubectl delete pod <one-web-pod-name> kubectl get pods # a new one is already being created!
8

Scale up (and back down)

Change the desired number of replicas with one command — no editing files needed:

kubectl scale deployment web --replicas=5 kubectl get pods # now 5 web pods kubectl scale deployment web --replicas=2
9

Inspect & clean up

kubectl get all # pods, deployments, services at a glance kubectl logs deployment/web # app logs kubectl describe pod <name> # detailed events (great for debugging) kubectl delete -f k8s/ # tear it all down minikube stop # stop the cluster (keeps it for next time)

Manifest Anatomy

Every Kubernetes object shares the same 4-part skeleton. Recognize it once and every manifest reads the same.

FieldWhat it means
apiVersionWhich API to use (e.g. apps/v1 for Deployments, v1 for Services/Secrets).
kindThe object type: Deployment, Service, Secret, Pod…
metadataName and labels that identify the object.
specThe desired state — what you want to exist.

The glue: labels & selectors

A Deployment stamps pods with a label (app: web). The Service's selector: app: web says "send traffic to any pod with that label." That loose coupling is how Services keep working as pods are created and destroyed.

kubectl Cheat Sheet

The commands you'll use every day. Bookmark this.

CommandWhat it does
kubectl apply -f file.yamlCreate/update objects from a manifest (or a whole folder)
kubectl get podsList pods (add -w to watch live)
kubectl get allList pods, deployments, services together
kubectl describe pod <name>Detailed status + events (your #1 debug tool)
kubectl logs <pod>Show a pod's logs (-f to follow)
kubectl exec -it <pod> -- bashOpen a shell inside a pod
kubectl scale deploy web --replicas=NChange how many copies run
kubectl delete pod <name>Delete a pod (Deployment recreates it)
kubectl delete -f file.yamlRemove objects defined in a manifest
kubectl rollout restart deploy webRestart all pods (e.g. after a new image)
minikube service <name>Open a NodePort service in the browser
minikube dashboardOpen the visual cluster dashboard

Troubleshooting

Pod statusLikely cause & fix
ErrImagePull / ImagePullBackOffCluster can't find the image — run minikube image load notes-app:1.0 and set imagePullPolicy: IfNotPresent.
CrashLoopBackOffApp keeps crashing — check kubectl logs <pod>. Often the DB isn't reachable yet.
PendingNo resources / cluster still starting — kubectl describe pod shows why.
Web can't reach the databaseService name or DATABASE_URL host must be db; check the Secret values.
minikube service hangsLeave the terminal open — it tunnels traffic; closing it closes the tunnel.
Changes not appliedRe-run kubectl apply -f k8s/; for a new image, kubectl rollout restart deploy web.

Your Challenge

Push your understanding before moving on:

  • Scale web to 4 replicas, then run kubectl get pods -o wide to see them.
  • Open minikube dashboard and watch a pod restart visually after you delete it.
  • Add a readiness probe to the web container so traffic only hits ready pods.
  • Bonus: give Postgres a PersistentVolumeClaim so its data survives a pod restart.
# add inside the web container spec, same level as ports: readinessProbe: httpGet: path: / port: 5000 initialDelaySeconds: 3 periodSeconds: 5 # then: kubectl apply -f k8s/web.yaml

Recap & What's Next

You can now

Run a local cluster, write Deployment/Service/Secret manifests, deploy a multi-tier app, and watch Kubernetes self-heal and scale it. That's the foundation of running software in production.

Next up: Module 9 — CI/CD, where you'll automate all of this — every git push builds your image, runs tests, and deploys it for you with GitHub Actions.

Kubernetes Intro

Objectives Why Kubernetes 5 Key Objects Install Hands-on Lab Manifest Anatomy Cheat Sheet Troubleshooting Challenge Recap