124 lines
3.7 KiB
Markdown
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
|
|
./show-url.sh
|
|
```
|
|
|
|
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
|
|
├── show-url.sh # Print the URL to open the app
|
|
└── README.md # This file
|
|
```
|