The number of times I have learned, forgotten and had to relearn this… I am going to end the cycle. These notes are going to be the bare minimum but will be enough to refresh my memory and be a cheat sheet for the basic commands. My source is Quickstart Kubernetes by Nigel Poulton.
Before I start, I did find this delightful comic by Google Cloud to introduce Kubernetes, what it is and why you need it
Kubernetes Architecture
This looks daunting but let us break it down
Cluster

Nodes
Machines in a cluster are called nodes. So basically the computer or a VM. Two types of nodes:
Control plane nodes - They run the internal K8 system services. In real world. it is common for clusters to have multiple control lane nodes and spread them to ensure high availability.

The main services it contains is:
- The API Server - The only part you interact with. You send all commands and queries here
- Scheduler - Which worker nodes to run on
- Store - Where application and cluster state are kept
- Cloud Controller - Integrates with Cloud services
- Bunch of other stuff you can google
Worker Nodes
The nodes are where applications run. Consist of 2 services:
- Kubelet - Basically the comunication piece, it talks with the control plane, find out what to do and also how the worker node is doing
- Container runtime - Internal management system that managed the containers like creating, starting and stopping

In this image, the container run time is Docker
Containers are run inside Pods. A Pod (as in a pod of whales or pea pod) is a group of one or more containers, with shared storage and network resources, and a specification for how to run the containers. Most times people run one container per pod but sometimes when multiple containers work together with shared resources they are all in one pod.
Why the hell does K8 not run containers directly?
The relationship of pods to clusters is why Kubernetes does not run containers directly, instead running pods to ensure that each container within them shares the same resources and local network. Grouping containers in this way allows them to communicate between each other as if they shared the same physical hardware, while still remaining isolated to some degree.
This organization of containers into pods is the basis for one of Kubernetes’ well-known features: replication. When containers are organized into pods, Kubernetes can use replication controllers to horizontally scale an application as needed. In effect, this means that if a single pod becomes overloaded, Kubernetes can automatically replicate it and deploy it to the cluster. In addition to supporting healthy functioning during periods of heavy load, Kubernetes pods are also often replicated continuously to provide failure resistance to the system
Pods make failure recovery easier. If a pod crashes, Kubernetes replaces the whole pod, keeping all its containers and settings intact. Containers inside a pod share the same internal IP address, making it easier for them to communicate.If Kubernetes scaled individual containers, it would need to reconfigure networking each time, leading to more overhead.
TLDR- Kubernetes duplicates pods instead of containers because pods keep everything organized, ensure smooth scaling, simplify networking, and improve reliability. Pods act like mini virtual machines inside a cluster, making Kubernetes more powerful and efficient

Kubectl
The command line tool that helps you manage K8s. From my limited experience, it is good to know some basics but get Lens or another IDE. There are not many open source ones now that Openlens is out but Seabird seems to be a good option.
Deploying my first pod
The book provides a github repo with a frontend app, that we can use. They have a yaml file that helps us deploy a pod
apiVersion: v1 kind: Pod metadata: name: first-pod labels: project: qsk-book spec: containers: - name: web-ctr image: nigelpoulton/qsk-book:1.0 ports: - containerPort: 8080
Definitions
apiVersion
defines the versioned schema of the Kubernetes API that the resource belongs to
kind
tells the type of K8 resources being defined
metadata
gives the Pod a name and label. This metadata helps further along when connecting to a servicespec
defines the containers the Pod will run. containerPort
Exposes port inside the container in this case 8080, since the webapp is listening on port 8080- containerPort is only informational for Kubernetes and does not expose the port outside the Pod.
- To make the application accessible externally, you need a Service (e.g., NodePort or LoadBalancer).
To deploy this use
kubectl apply
, so kubectl apply -f pod.yml
. To see if the pod is running, kb get pods
To get ad detailed description of the pod use
kubectl describe pod <pod-name>
The Pod has an IP address but this is internal and not accessible from outside the cluser. We need a K8 service if you want to access from utside the cluster.
Service
A Service is a Kubernetes object designed to provide stable networking for Pods.

Looking at the provided
svc.yml
kind: Service apiVersion: v1 metadata: name: svc-lb spec: type: LoadBalancer ports: - port: 5555 targetPort: 8080 selector: project: qsk-book
Similar to Pod yaml file. the metadata contains the service name. Other pods can invoke this name to access the Pods behind it
The spec is the crucial section. It basically port forwards the traffic from 5555 to 8080.
Labels are the main way that K8 connects objects ( Things running on Kubernetes like Pods and Services). For example,
qsk-book
tells the Service accepts traffic on port 5555
and forwards it to all Pods with the project=qsk-book
label on port 8080

Cluster-IP is the internal IP address and what pods on same cluster use to communicate
The
EXTERNAL-IP
is the address we’ll use to connect to the appThe
PORT(S)
column lists the ports the Service is accessible on. To remove pods
kubectl delete pod first-pod
Deployments
A Kubernetes Deployment tells Kubernetes how to create or modify instances of the pods that hold a containerized application.

This figure is a good illustration of the layers:
- The application at the center
- The container adds the app dependencies and OS
- The Pod specs provide the metadata to be schedules on Kubertnes
- The deployment adds features such as scaling, self-healing and rollout
There are 2 main parts to deployments:
- The object - This holds the definition, basically what the desired state should be
- The controller - Implements what the object wants and makes sure it runs properly
The Deployment controller is constantly watching the cluster and will notice the change, so in this case, if the number of pods fall before 5 (the requested number), it will start a new Pod to brin g the observed state back into sync with desired state. Technically called reconcilation, but self-healing sounds better.

If a worker node fails, all pods running on the node are lost. Deployment controller can start replacements on surviving nodes. Nodes can not be replaced by deployment
Scaling the app
Kubernetes have objects that enable automatic scaling, but focus on manual in these notes
Declarative Method
Basically, you update the YAML file and apply it with
kubectl
Imperative method
kubectl scale
command helps scale the number of pods but is not as recommended as the declarative method Labels are how deployments know what know what pods it created and managed. If you change the label of a pod in a deployment, the deployment would assume the pod has been lost and recreate the pod
The reason declarative is preferred is because the scaling is recorded on the YAML file and is not lost. If scaled manually (imperative method) and then later the YAML file is applied, the manual scaling is lost
Performing Rolling Updates
In the book, the example they performed a rolling update by adding the following lines
minReadySeconds: 20 strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 0 maxSurge: 1
so the complete deployment file is
# 2022 version apiVersion: apps/v1 kind: Deployment metadata: name: qsk-deploy spec: replicas: 5 selector: matchLabels: project: qsk-book minReadySeconds: 20 strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 0 maxSurge: 1 template: metadata: labels: project: qsk-book spec: containers: - name: qsk-pod imagePullPolicy: Always ports: - containerPort: 8080 image: nigelpoulton/qsk-book:1.1
minReadySeconds tells K8 the time to wait after updating each replica. Inserting wait times like this, allows us the ability to run tests and make sure the new replicas are working as expected. Since an update in K8 means creating new resources and deleting old ones.
The strategy tells what is the update plan. RollingUpdate means it updates one replica at a time and is different to Recreate while deletes and replaces all Pods in one go
maxSurge=1 means K8 can add one extra Pod during rollout and maxUnavailable=0 means it cant go below 5 pods. Combined it means, we can have a 6th replica with the new verion and delete ar replica running the old version
Apply the new YAML with
kubectl
. To observe, the rollout use the following commandkubectl rollout status deployment qsk-deploy
Remember this deployment just handles pods, to actually see the app, we need to provide a LoadBalancer service than can connect to the app.