# Kubernetes Fundamentals
:::warning
[toc]
:::

### What is Kubernetes
:::success
Kubernetes (K8s) is an open-source, portable, and extensible platform designed to automate the deployment, scaling, and management of containerized applications. Originally developed by Google, it represents over 15 years of experience in running production workloads at scale. At its core, Kubernetes functions as a distributed system framework that drives a cluster toward a user-defined desired state through continuous, independent control loops.
:::
**Critical Takeaways:**
:::info
- **Declarative Management**: Unlike traditional orchestration that follows a defined A-to-B-to-C workflow, Kubernetes uses a set of independent control processes that continuously monitor the current state and make adjustments to match the provided specification.
- **Atomic Units (Pods)**: The smallest deployable unit in Kubernetes is the Pod, which represents one or more tightly coupled containers sharing storage and network resources.
Architecture: The system is divided into a Control Plane, which makes global decisions about the cluster, and Nodes, which serve as the worker machines running the actual application workloads.
- **Resiliency and Self-Healing**: Kubernetes provides built-in mechanisms for automated rollouts, rollbacks, service discovery, load balancing, and self-healing (restarting or replacing failed containers).
- **Flexibility**: It is not a monolithic PaaS; it provides building blocks (pluggable logging, monitoring, and storage) while preserving user choice in configuration and CI/CD workflows.
:::
### Why Kubernetes

---
### Kubernetes Architecture
---
**Cluster Architecture and Components**
:::success
Kubernetes operates on a hub-and-spoke model where all communication is centralized through the API server. A cluster is composed of two primary resource types: the Control Plane and worker Nodes.
:::

---
**Control Plane Components**
---
:::info

The Control Plane manages the overall state of the cluster, detecting and responding to cluster events.
| Component | Function |
|--------------------------|-------------------------------------------------------------------------|
| kube-apiserver | The front end for the control plane; exposes the Kubernetes API (HTTP). Designed to scale horizontally. |
| etcd | A consistent, highly-available key-value store used as the backing store for all cluster data. |
| kube-scheduler | Watches for newly created Pods with no assigned node and selects a suitable node based on resource requirements and constraints. |
| kube-controller-manager | Runs controller processes (e.g., Node, Job, EndpointSlice) to implement API behavior. |
| cloud-controller-manager | (Optional) Links the cluster to a cloud provider's API, separating cloud-specific logic from the core cluster logic. |
:::
**Node (Worker) Components**
:::info

Nodes host the Pods that comprise the application workload. Every node must run three essential services:
| Component | Function |
|--------------------|--------------------------------------------------------------------------|
| kubelet | An agent that ensures containers are running within a Pod and remain healthy according to the provided PodSpecs. |
| kube-proxy | A network proxy that maintains network rules on nodes, enabling communication to Pods from inside or outside the cluster. |
| Container Runtime | The software responsible for running containers (e.g., containerd, CRI-O). |
:::
---
### Kubernetes Cluster Setup Guide (Minikube & k3s)
---
**Prerequisites**
:::warning
- Ubuntu 22.04 / 24.04 (or similar Linux VM)
- Minimum:
- 2 CPU
- 4 GB RAM
- Internet access
- sudo privileges
:::
#### Option 1: Minikube Setup
:::success
**Step 1: Install Dependencies**
```bash
sudo apt update
sudo apt install -y curl wget apt-transport-https
```
**Step 2: Install kubectl**
```bash
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/
Verify:
kubectl version --client
```
**Step 3: Install Minikube**
```bash=
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
Verify:
minikube version
```
**Step 4: Install Container Runtime (Docker)**
```bash=
sudo apt install -y docker.io
sudo systemctl enable docker
sudo systemctl start docker
sudo usermod -aG docker $USER
newgrp docker
```
**Step 5: Start Minikube Cluster**
```bash=
minikube start --driver=docker
```
**Step 6: Verify Cluster**
```bash=
kubectl get nodes
Expected output:
NAME STATUS ROLES AGE VERSION
minikube Ready control-plane ...
```
**Step 7: Deploy Test App**
```bash=
kubectl create deployment nginx --image=nginx
kubectl expose deployment nginx --type=NodePort --port=80
Access:
minikube service nginx
```
:::
#### Option 2: k3s Setup
:::info
**Step 1: Install k3s**
```bash=
curl -sfL https://get.k3s.io | sh -
```
**Step 2: Check Service Status**
```bash=
sudo systemctl status k3s
```
**Step 3: Creating Command alias for Kubectl (Optional)**
```bash=
alias kc='sudo k3s kubectl'
kc get node
````
**Step 4: Verify Cluster**
```bash=
kc get nodes
Expected:
NAME STATUS ROLES AGE VERSION
<hostname> Ready control-plane,master ...
```
**Grab the K3S_TOKEN from the Manager**
```
sudo cat /var/lib/rancher/k3s/server/node-token
```
:bulb: *Please copy the **token**, as it will be required when adding a node to the cluster.*
**Step 5: Add a worker node to the cluster**
```bash=
Command:
curl -sfL https://get.k3s.io | K3S_URL=https://myserver:6443 K3S_TOKEN=mynodetoken sh -
Example (DO-LAB):
curl -sfL https://get.k3s.io | K3S_URL=https://165.227.225.148:6443 K3S_TOKEN=K10a810c11f1bfc253cbdbf63c6bbad2a5bc7fb67eafd91b007a30569b723d48a28::server:3a078e28e0f52fccfd8650871cddb068 sh -
Example (SL-Lab):
curl -sfL https://get.k3s.io | K3S_URL=https://172.31.20.160:6443 K3S_TOKEN=K10cf647253f2fcaa1475358866ccbc621f6fb2115f4e644a3437350709068a336f::server:a0522cff7f73f3132be946f5735cdc56 sh -
```
**Step 5: Deploy Test App**
```bash=
kubectl create deployment nginx --image=nginx
kubectl expose deployment nginx --type=NodePort --port=80
```
**Step 6: Access Application**
```bash=
Get NodePort:
kubectl get svc nginx
Access:
http://<VM-IP>:<NodePort>
```
:::
#### Option 3: microk8s Setup
:::success
**1 Preparation**
```bash
> Connect via SSH, example: `ssh lab123.kubelabs.tk`
> Run on the server:
sudo apt update
sudo iptables -P FORWARD ACCEPT
````
**2. Installation**
> <https://microk8s.io/>
```bash
sudo snap install microk8s --classic
sudo microk8s status --wait-ready
```
> Result:
>
> microk8s (1.23/stable) v1.23.3 from Canonical ✓ installed
> To install a specific version: `--channel=1.22/stable`
**2.1. Post-Installation**
```bash
./post-install.sh
```
**2.2. Permissions to run microk8s**
```bash
sudo usermod -a -G microk8s kube
newgrp microk8s
```
**2.3. Install addons**
```bash
sudo snap install kubectl --classic
sudo microk8s.enable dns dashboard storage ingress
```
**2.4. Enable remote cluster administration**
```bash
mkdir .kube
sudo microk8s kubectl config set-cluster microk8s-cluster \
--server=https://<PUBLIC_IP>:16443 \
--insecure-skip-tls-verify
# Restart the cluster
microk8s stop
microk8s start
```
> Another option using stop/start
```bash
sudo systemctl restart snap.microk8s.daemon-apiserver-kicker.service
```
> In case the KUBE-API is not exposed automatically
```bash
sudo sh -c 'echo "--allow-privileged=true" >> /var/snap/microk8s/current/args/kube-apiserver'
```
**2.5. Export the .kube/config configuration**
```bash
microk8s config > ~/.kube/config
cat ~/.kube/config
```
**2.6. Verify the MicroK8s installation**
```bash
kubectl get nodes
kubectl describe nodes
```
:::
#### Key differences
:::success
| Feature | Minikube | k3s |
|----------------|-----------------------------------|-------------------------------------|
| Primary Use | Learning, local development | Lightweight production, edge, labs |
| Installation | Multi-step setup | Single script / binary |
| Architecture | Runs inside VM or Docker | Runs directly on host (bare metal) |
| Resource Usage | Moderate | Very low |
| Startup Time | Slower | Fast |
| Components | Standard Kubernetes components | Simplified, optimized components |
| Container Runtime | Docker / containerd | containerd (default) |
| HA Support | Limited (single-node by default) | Supports multi-node & HA setups |
| Cloud Native | No direct cloud integration | Can integrate with cloud setups |
:::
#### Cleanup
:::warning
**Minikube**
```
minikube delete
```
**k3s**
```
sudo /usr/local/bin/k3s-uninstall.sh
```
:::
### Working with Kubernetes Objects
---
#### Pods
---
Pods are the smallest deployable units of computing that you can create and manage in Kubernetes.

:arrow_right: *Source: https://kubernetes.io/docs/*
---
#### Pods inside a worker node
---

:arrow_right: *Source: https://kubernetes.io/docs/*
---
**The Kubernetes Abstraction Hierarchy**
---

### Working with Kubernetes Objects
#### Explore your Kubernetes cluster
````yaml=
kubectl version
kubectl cluster-info
kubectl api-resources ## Get all API Object list
kubectl get nodes (nodes/node/no)
kubectl get pods (pods/pod/po)
kubectl get namespaces (namespaces/namespace/ns)
kubectl get pods --all-namespaces
kubectl get pods -n kube-system
kubectl get pods [pod name]
kubectl get pods -o wide --all-namespaces #Show pods along with nodes
kubectl get pods -o wide --all-namespaces | grep <node> #Show pods on specified node
kubectl describe node <node-name> #Show all of the non-terminated pods running on that node
````

#### YAML Syntax for Kubernetes
**Structure**
:::warning
A - API version
K - Kind ## this defines the type of object/primitive
M - Metadata
S - Specs
:::

---
### Class Exercises
---
#### Demo 1: Creating and exploring objects
````yaml=
kubectl run pingpong --image alpine ping 1.1.1.1
kubectl get all
kubectl logs pod/pingpong ==> get logs from a random pod within a deploymnt
kubectl logs pod/pingpong --tail 5
kubectl logs pod/pingpong --tail 1 --follow
kubectl logs -l run=pingpong --tail 1 -f ==> get logs from all pods within a deployment
kubectl describe pod <podname>
````
**Demo 2: Create a basic pod via YAML**
**pod1.yaml**
```yaml=
apiVersion: v1
kind: Pod
metadata:
name: redis
labels:
name: redis
app: demo
spec:
containers:
- name: redis
image: redis:latest
ports:
- containerPort: 6379
protocol: TCP
```
**Commands**
```bash=
## Create k8s Object
kubectl create -f pod1.yaml
## Explore and validate
kubectl get pods
kubectl get pods -o wide
kubectl get pods -o yaml
kubectl describe pods
```
#### Demo 3: YAML Introduction with a Pod Manifest
**Objective**
:::success
Show how to create resources declaratively.
:::
File: pod-nginx.yaml
```yaml=
apiVersion: v1
kind: Pod
metadata:
name: nginx-yaml-pod
labels:
app: nginx-demo
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
```
**Commands**
```bash=
kubectl apply -f pod-nginx.yaml
kubectl get pods
kubectl describe pod nginx-yaml-pod
```
#### Demo 4: Inspect Live YAML and Learn the API Shape
**Commands**
```bash=
kubectl get pod nginx-yaml-pod -o yaml
kubectl get pod nginx-yaml-pod -o wide
kubectl explain pod
kubectl explain pod.spec.containers
```
#### Demo 5: Create Your First Deployment
**Objective**
:::success
Show how Kubernetes manages Pods through a higher-level controller.
:::
**File: deployment-nginx.yaml**
```yaml=
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
spec:
replicas: 2
selector:
matchLabels:
app: nginx-deploy
template:
metadata:
labels:
app: nginx-deploy
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
```
**Commands**
```bash=
kubectl apply -f deployment-nginx.yaml
kubectl get deployments
kubectl get replicasets
kubectl get pods -l app=nginx-deploy
```
#### Demo 6: Scale a Deployment
**Objective**
:::success
Demonstrate horizontal scaling.
:::
**Commands**
```bash=
kubectl scale deployment nginx-deploy --replicas=4
kubectl get deployment nginx-deploy
kubectl get pods -l app=nginx-deploy
kubectl get pods -w
```
:bulb: *-w (watch) → “Keep watching for changes in real time”*
:bulb: *-l (label) -> shows all the pods matching the label*
:bulb: *Scaling in Kubernetes is typically just a change in desired state. The platform handles creating or removing Pods.*
### References
:::info
- [Kubernetes Concepts](https://kubernetes.io/docs/concepts/)
- [Kubernetes Tutorials](https://kubernetes.io/docs/tutorials/)
- https://k3s.io/
:::