Kubernetes Quickstart

Kubernetes Quickstart

Tags
devops
Published
Link
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

A group of nodes that work together to run a containerized application. Wherever you install and run K8s is called a cluster (A Kubernetes cluster is one or more machines with Kubernetes installed). Here is one cluster, cos they are all connected together
notion image

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.
notion image
The main services it contains is:
  1. The API Server - The only part you interact with. You send all commands and queries here
  1. Scheduler - Which worker nodes to run on
  1. Store - Where application and cluster state are kept
  1. Cloud Controller - Integrates with Cloud services
  1. 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
notion image
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
 
 
notion image

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
notion image
kind tells the type of K8 resources being defined
notion image
metadata gives the Pod a name and label. This metadata helps further along when connecting to a service
spec 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.
notion image
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
 
notion image
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 app
The 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.
 
 
notion image
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.
Figure explains the meaning of the various fields in the yaml file
Figure explains the meaning of the various fields in the yaml file
 
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 command
kubectl 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.