# 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 ./show-url.sh ``` Or open manually: - **Minikube:** `minikube service notes-web-service -n notes-app` - **Other:** `http://: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 ├── show-url.sh # Print the URL to open the app └── README.md # This file ```