Files
Severed-Blog/_posts/blog_app/2025-12-27-part-1.md
2025-12-30 23:57:50 -05:00

136 lines
4.4 KiB
Markdown

---
layout: post
title: 'Step 1: K3d Cluster Architecture'
date: 2025-12-28 09:00:00 -0400
categories:
- blog_app
highlight: true
---
[[2025-12-27-intro]]
# 1. K3d Cluster Architecture
In a standard Docker setup, containers share the host's kernel and networking space directly. In Kubernetes, we introduce an abstraction layer: a **Cluster**. For this project, we use **K3d**, which packages **K3s** (a lightweight production-grade K8s distribution) into Docker containers.
```text
Severed-Infra % tree
.
├── README.md
├── apps
│ ├── severed-blog-config.yaml
│ ├── severed-blog-hpa.yaml
│ ├── severed-blog-service.yaml
│ ├── severed-blog.yaml
│ └── severed-ingress.yaml
├── infra
│ ├── alloy-env.yaml
│ ├── alloy-setup.yaml
│ ├── dashboard
│ │ ├── dashboard-admin.yaml
│ │ ├── permanent-token.yaml
│ │ └── traefik-config.yaml
│ ├── observer
│ │ ├── adapter-values.yaml
│ │ ├── dashboard-json.yaml
│ │ ├── grafana-ingress.yaml
│ │ ├── grafana.yaml
│ │ ├── loki.yaml
│ │ └── prometheus.yaml
│ └── storage
│ └── openebs-sc.yaml
├── namespaces.yaml
└── scripts
├── README.md
├── access-hub.sh
├── deploy-all.sh
├── setup-grafana-creds.sh
└── tests
├── generated-202-404-blog.sh
└── stress-blog.sh
```
## 1.1 Multi-Node Simulation
- **Server (Control Plane):** The master node. Runs the API server, scheduler, and etcd.
- **Agents (Workers):** The worker nodes where our application pods run.
### Setting up the environment
We map port `8080` to the internal Traefik LoadBalancer to access services via `*.localhost`.
```bash
k3d cluster create severed-cluster \
--agents 2 \
-p "8080:80@loadbalancer" \
-p "8443:443@loadbalancer"
```
## 1.2 Image Registry Lifecycle
Since our `severed-blog` image is local, we side-load it directly into the cluster's internal image store rather than pushing to Docker Hub.
```bash
docker build -t severed-blog:v0.3 .
k3d image import severed-blog:v0.3 -c severed-cluster
```
## 1.3 Namespaces & Storage
We partition the cluster into logical domains. We also install **OpenEBS** to provide dynamic storage provisioning (PersistentVolumes) for our databases.
**`namespaces.yaml`**
```yaml
apiVersion: v1
kind: Namespace
metadata:
name: severed-apps
---
apiVersion: v1
kind: Namespace
metadata:
name: monitoring
---
apiVersion: v1
kind: Namespace
metadata:
name: kubernetes-dashboard
---
apiVersion: v1
kind: Namespace
metadata:
name: openebs
```
**`infra/storage/openebs-sc.yaml`**
```yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: severed-storage
provisioner: openebs.io/local
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
```
---
## 1.4. Infrastructure Concepts Cheat Sheet
| Object | Docker Equivalent | Kubernetes Purpose |
| ----------- | ------------------------------ | ----------------------------------------------------------------- |
| Node | The Host Machine | A physical or virtual server in the cluster. |
| Pod | A Container | The smallest deployable unit (can contain multiple containers). |
| Deployments | `docker-compose up` | Manages the lifecycle and scaling of Pods. |
| Services | Network Aliases | Provides a stable DNS name/IP for a group of Pods. |
| HPA | Auto-Scaling Group | Automatically scales replicas based on traffic/load. |
| Ingress | Nginx Proxy / Traefik | Manages external access to Services via HTTP/HTTPS. |
| ConfigMap | `docker run -v config:/etc...` | Decouples configuration files from the container image. |
| Secret | Environment Variables (Secure) | Stores sensitive data (passwords, tokens) encoded in Base64. |
| DaemonSet | `mode: global` (Swarm) | Ensures one copy of a Pod runs on _every_ Node (logs/monitoring). |
| StatefulSet | N/A | Manages apps requiring stable identities and storage (Databases). |
[[2025-12-27-part-2]]