ZKT26/Z2/z2/README.md

124 lines
3.7 KiB
Markdown

# Notes App — Kubernetes Deployment
A simple web application where you can write, view, and delete notes. Built with Flask (Python) and PostgreSQL.
---
## What the app does
- Add a note using the text box on the main page
- View all saved notes
- Delete any note with a button click
- Notes are stored in a PostgreSQL database and survive pod restarts
---
## Containers used
| Container | Image | Description |
|-----------|-------|-------------|
| `notes-web` | `notes-web:latest` (built locally) | Flask web app — serves the UI and handles requests |
| `postgres` | `postgres:15-alpine` | PostgreSQL database — stores notes |
---
## Kubernetes objects
| Object | Name | Description |
|--------|------|-------------|
| Namespace | `notes-app` | Isolates all app objects from other workloads |
| Deployment | `notes-web` | Runs 2 replicas of the Flask web app |
| StatefulSet | `postgres` | Runs 1 PostgreSQL pod with stable identity |
| PersistentVolume | `postgres-pv` | 1Gi volume backed by host path `/mnt/notes-postgres-data` |
| PersistentVolumeClaim | `postgres-pvc` | Claims the PV for use by the StatefulSet |
| Service (NodePort) | `notes-web-service` | Exposes the web app on port `30080` |
| Service (ClusterIP) | `postgres-service` | Internal access to PostgreSQL for the web app |
| Service (Headless) | `postgres-headless` | Required by the StatefulSet for stable DNS |
---
## Networking and volumes
**Services:**
- `notes-web-service` — NodePort, exposes port `30080` externally → routes to pod port `5000`
- `postgres-service` — ClusterIP, internal only, port `5432` → the web app connects to this
- `postgres-headless` — Headless service (no ClusterIP) used by the StatefulSet
**Volume:**
- `postgres-pv` uses a `hostPath` at `/mnt/notes-postgres-data` on the node
- Data persists even if the PostgreSQL pod is restarted or recreated
---
## Container configuration
**notes-web:**
- Environment variables set the database connection: `DB_HOST`, `DB_PORT`, `DB_NAME`, `DB_USER`, `DB_PASS`
- `imagePullPolicy: Never` — uses the locally built image (no registry needed)
- Runs on port `5000`
**postgres:**
- `POSTGRES_DB`, `POSTGRES_USER`, `POSTGRES_PASSWORD` configure the database on first start
- Data directory `/var/lib/postgresql/data` is mounted from the PVC
---
## How to use
### 1. Prepare (build image, create host directory)
```bash
chmod +x prepare-app.sh start-app.sh stop-app.sh show-url.sh
./prepare-app.sh
```
### 2. Start the application
```bash
./start-app.sh
```
### 3. Open in browser
```bash
http://localhost:8080/ - **Port-forwarding has been done already**
```
Or open manually:
- **Minikube:** `minikube service notes-web-service -n notes-app`
- **Other:** `http://<node-ip>:30080`
### 4. Stop (keep objects, scale down)
```bash
kubectl scale deployment notes-web -n notes-app --replicas=0
kubectl scale statefulset postgres -n notes-app --replicas=0
```
### 5. Delete everything
```bash
./stop-app.sh
```
---
## File overview
```
z2/
├── app/
│ ├── app.py # Flask application
│ ├── requirements.txt # Python dependencies
│ └── Dockerfile # Image definition for notes-web
├── namespace.yaml # Namespace: notes-app
├── deployment.yaml # Deployment: notes-web (Flask)
├── statefulset.yaml # StatefulSet + PV + PVC (PostgreSQL)
├── service.yaml # Services: notes-web-service, postgres-service
├── prepare-app.sh # Build image, create host directory
├── start-app.sh # Apply all Kubernetes objects
├── stop-app.sh # Delete all Kubernetes objects
├── status.sh # Print the status of Namespace, PV, PVC, PODS and Services
└── README.md # This file
```