# Kubernetes and Helm

***

[Kubernetes Playground in your browser](https://killercoda.com/playgrounds/scenario/kubernetes)

[K3d](https://k3d.io/stable/usage/configfile/) for local practice

[Headlamp](https://headlamp.dev/) for Kubernetes UI

***

### **Core Building Blocks**

***Cluster*** — The overall system, made up of a control plane and worker nodes.

***Node*** — A physical or virtual machine in the cluster. There are two types: the **control plane node** (manages the cluster) and **worker nodes** (run your workloads).

***Pod*** — The smallest deployable unit in K8s. A pod wraps one or more containers that share networking and storage.

<details>

<summary>What is <code>kubelet</code>?</summary>

**kubelet** is an agent process that runs on every **worker node**. Its job is to be the local manager for that node — it talks to the **API server** and makes sure the containers described in pod specs are actually running and healthy on its node.

**Think of it this way:** the API server is like a central commander issuing orders, and the kubelet on each node is the local soldier carrying them out. When the scheduler decides "Pod X should run on Node 2," it's the kubelet on Node 2 that actually pulls the container image and starts it.

**A few key things kubelet does:**

* Watches the API server for pods assigned to its node
* Tells the container runtime (like `containerd` or Docker) to start/stop containers
* Reports the node's health and pod status back to the control plane
* Runs liveness and readiness probes to check if containers are healthy

It's worth noting that kubelet is one of the few Kubernetes components that is *not* itself containerized — it runs as a native system process on the node, because it **needs to be running before any containers can be started**.

</details>

***

#### **Workload Resources**

***Deployment*** — Manages a set of identical pods, handles rolling updates and rollbacks.

***ReplicaSet*** — Ensures a specified number of pod replicas are running at all times (usually managed by a Deployment).

***StatefulSet*** — Like a Deployment but for stateful apps (databases, etc.) — preserves pod identity and storage.

***DaemonSet*** — Runs a copy of a pod on every node (e.g., for logging or monitoring agents).

***Job / CronJob*** — Runs pods to completion; CronJob does it on a schedule.

***

#### **Networking**

***Service*** — A stable network endpoint to expose pods. Types include ClusterIP, NodePort, and LoadBalancer.

***Ingress*** — Manages external HTTP/HTTPS access to services, often with routing rules.

***DNS*** — K8s has built-in DNS so services can find each other by name.

***

#### **Configuration & Storage**

***ConfigMap*** — Stores non-sensitive configuration data as key-value pairs.

***Secret*** — Stores sensitive data (passwords, tokens) in base64-encoded form.

***PersistentVolume (PV) / PersistentVolumeClaim (PVC)*** — PV is a piece of storage provisioned in the cluster; PVC is a request for that storage by a pod.

***

#### **Scheduling & Organization**

***Namespace*** — Virtual clusters within a cluster, used to isolate resources by team or environment.

***Labels & Selectors*** — Key-value tags on objects used to organize and select resources.

***Taints & Tolerations*** — Control which pods can be scheduled on which nodes.

***Affinity / Anti-affinity*** — Rules to attract or repel pods from certain nodes.

***

#### **Control Plane Components**

***API Server*** — The front door to the cluster; all kubectl commands go here.

***etcd*** — The distributed key-value store that holds all cluster state.

***Scheduler*** — Assigns pods to nodes based on resource availability and constraints.

***Controller Manager*** — Runs controllers that reconcile desired state with actual state.

***

**Here are 6 diagrams covering the full picture:**

{% embed url="<https://claude.ai/public/artifacts/8a4c2bfa-20f5-4ff1-a605-6aee573750e3>" %}

1. **Cluster Architecture** — Control plane components (API server, etcd, scheduler, controller manager) and their relationship to worker nodes and pods
2. **Workload Resources** — How Deployments → ReplicaSets → Pods relate, plus StatefulSets, DaemonSets, Jobs, and CronJobs
3. **Networking & Traffic Flow** — Sequence diagram showing a request traveling from the Internet → LoadBalancer → Ingress → Service → Pods
4. **Configuration & Storage** — How ConfigMaps, Secrets, PVs, and PVCs are consumed by pods
5. **Scheduling** — How labels, taints/tolerations, and affinity rules decide which pod lands on which node
6. **Helm** — How a single Chart + different value files produces different releases per environment

***

### **Key CLI Tool**

`kubectl` is the command-line tool you use to interact with your cluster — deploying apps, inspecting resources, viewing logs, etc.

***

### Mapping Docker concepts to Kubernetes (i.e. comparing the 2)

This is one of the most practical mental shifts when moving to Kubernetes.

#### The Core Idea

**Docker Compose** and **Kubernetes** are solving the same problem — "run my multi-container app" — but at different scales and with different philosophies.

In Compose, you describe everything in **one file** and it runs on **one machine**. In Kubernetes, you describe everything in **multiple files** and it runs across **a cluster of machines**.

***

#### The Conceptual Mapping

| Docker Compose         | Kubernetes Equivalent                              |
| ---------------------- | -------------------------------------------------- |
| `docker-compose.yml`   | Multiple YAML manifests (or a Helm chart)          |
| `service:` block       | Deployment + Service (two separate objects)        |
| `image:`               | Same — container image reference inside a Pod spec |
| `ports:`               | Service (ClusterIP, NodePort, or LoadBalancer)     |
| `environment:`         | ConfigMap or Secret                                |
| `volumes:`             | PersistentVolume + PersistentVolumeClaim           |
| `networks:`            | Handled automatically by K8s networking            |
| `depends_on:`          | No direct equivalent — apps must handle retries    |
| `replicas:` (in Swarm) | `replicas:` in a Deployment spec                   |

***

#### A Concrete Example

Say you have a simple web app + database in Compose:

```yaml
# docker-compose.yml
services:
  web:
    image: myapp:latest
    ports:
      - "80:3000"
    environment:
      DB_HOST: db
      DB_PASS: secret123
    depends_on:
      - db

  db:
    image: postgres:15
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata:
```

In Kubernetes, this single file **splits into roughly 5 objects:**

**1. Deployment** for the web app (defines the pod template, image, replicas)

**2. Service** for the web app (exposes it — internally or externally via LoadBalancer)

**3. Deployment** for postgres (or more properly, a StatefulSet)

**4. Service** for postgres (so the web app can reach it by DNS name)

**5. PersistentVolumeClaim** for the postgres data volume

Plus a **Secret** for `DB_PASS` and a **ConfigMap** for `DB_HOST` — rather than hardcoding them in the manifest.

***

#### The Biggest Mindset Shifts

**Services are split in two.** In Compose, one `service:` block covers both "what runs" and "how it's reached." In K8s, a Deployment handles "what runs" and a Service handles "how it's reached." They're separate objects linked by label selectors.

**Networking is automatic.** In Compose you define networks explicitly. In K8s, every pod can reach every other pod by default, and services get a DNS name automatically (e.g. `postgres-service.default.svc.cluster.local`, or just `postgres-service` within the same namespace).

**`depends_on` doesn't exist.** Compose can wait for a container to start before starting another. Kubernetes has no such guarantee — it just keeps restarting crashing pods until dependencies are ready. Your app needs to handle connection retries gracefully.

**Volumes are first-class infrastructure.** A Compose volume is just a named Docker volume on the host. A K8s PVC is a formal request for storage that could be backed by cloud storage, NFS, or anything else — it's decoupled from the pod.

**Scaling is built in.** In Compose you'd run `docker compose up --scale web=3`. In K8s you just set `replicas: 3` in your Deployment, or use an autoscaler, and K8s spreads those pods across nodes automatically.

***

#### Tools That Help

**Kompose** is an official tool that literally converts a `docker-compose.yml` into Kubernetes manifests automatically. It's a great way to see the transformation in practice — though the output usually needs some cleanup before being production-ready.

The output of `kompose convert` on the example above would give you exactly those 5+ YAML files, ready to apply with `kubectl apply -f`.

***

### Mapping Docker concepts to Kubernetes: Visualization

{% embed url="<https://claude.ai/public/artifacts/b0b7f7eb-f93a-4830-b17a-972f519499d1>" %}

7 diagrams covering every key transformation:

1. **One Machine vs. A Cluster** — the fundamental runtime difference
2. **Concept-by-Concept Mapping** — every Compose field and its K8s counterpart (including the dead-end `depends_on`)
3. **The Service Split** — the most important difference: one Compose block → Deployment + Service linked by labels
4. **Full App Transformation** — a 2-service Compose file expanding into 6+ K8s objects
5. **Networking** — explicit named networks vs. automatic DNS-based service discovery
6. **depends\_on → Retry Logic** — sequence diagram showing the CrashLoopBackOff dance K8s does instead
7. **Kompose** — the automated conversion tool and what manual cleanup still remains afterward

***

### Video explainer about Kubernetes

{% embed url="<https://www.youtube.com/watch?v=TlHvYWVUZyc&pp=ygULa3ViZXJuZXRlcyA%3D>" %}

***
